Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

1. Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 04/08/2016 - 02:01h

A utilizarmos o comando while como o exemplo:

while read LINE;do
echo $LINE
done < File.txt


É possível manipular o conteúdo de $LINE como se fosse um índice de um vetor?
Pelo que pude entender, o while pega linha por linha, segue as instruções contidas dentro do bloco do laço e depois passa para a próxima linha e assim por diante até chegar ao final do arquivo e encerrar a execução.
Mas como é que o while tem o controle para as linhas que já foram lidas das que ainda serão lidas?
A mesma situação, meramente explicativa, ocorre no comando for i in `cat File.txt`;do comandos...; done
Como será que funciona o mecanismo de controle no momento em que o arquivo é lido pelo while (done < File.txt).
Mais precisamente, como que é realizado o controle para que a execução fique "travada" na linha X e depois somente vá para a linha Y e assim por diante? Será que cada linha não recebe um índice que internamente o while utiliza para cada linha lida? Há como fazer com que o while deixe isto explícito?

Trabalho com manipulação de arquivos text com milhares, senão milhões de linhas. Eu necessito saber se isso é possível de se fazer, pois caso contrário eu utilizarei vetores para meu propósito (o que eu não gostaria de ter de fazer, pois já realizei testes e popular um vetor com muitas linhas consome muito tempo de execução). Então seria ganho de tempo aproveitar os recursos do while. Necessito que, durante a execução do laço, seja possível escolher as linha que será lida aleatoriamente. Por exemplo, durante determinado momento da execução, supomos que eu esteja na linha 4. Na próxima interação, desejo passar para a linha 25, e por aí vai...

Deixo claro que não estou solicitando ajuda para implementar um algoritmo e sim precisar sobre a questão dos recursos do while.



  


2. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

Nuno Leitao
nunogrl

(usa Outra)

Enviado em 04/08/2016 - 15:04h

"Trabalho com manipulação de arquivos text com milhares, senão milhões de linhas."

Se esse é o seu caso, mantenha-se longe do while.

O while funciona enquanto o comando read não devolver 0.


3. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

thinomar
thinomar

(usa Linux Mint)

Enviado em 04/08/2016 - 17:38h

É... não encontrei nada a respeito, nem o source code do While. Mas não dá pra usar um contador?
--
-I've been talking to the main computer
-And...?
-It hates me


4. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 04/08/2016 - 17:44h

Não pode ser utilizado contador, pois estamos falando do funcionamento interno do while.
Pensei em algo relacionado a passagem de parâmetros ou algo do tipo.


5. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as c

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/08/2016 - 20:53h

O comando read lê sempre uma linha de cada vez, independentemente do comprimento que essas linhas tenham. Como isso funciona? Em algum lugar dentro do shell (ou das bibliotecas que ele usa), ele lê caráter por caráter, e vai acumulando os caracteres lidos num buffer, até encontrar um caráter que corresponda à marca de fim de linha (que no mundo UNIX é o byte que tem o valor 10). Na próxima ocorrência de read sobre a mesma fonte de dados, a leitura continua do ponto onde parou (i.e. do caráter após a marca de fim de linha que significou o fim da linha anterior).

O shell não conta a quantidade de linhas ou de caracteres lidos (a não ser que você peça para ler uma quantidade limitada de caracteres -- veja na documentação do comando read sobre a opção -N). Mas o fato de ele não o fazer não o impede de implementar um contador por conta própria.

n_linhas=0
while read linha; do
((n_linhas++))
done < arquivo
echo "O arquivo tem $n_linhas linhas."


[[ Estou de saída agora. Quando voltar, continuo a responder. ]]


6. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as como

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 05/08/2016 - 00:59h

Eu entendo, e na realidade sei exatamente como fazer isso, mas a questão do tópico é que eu desejo saber se é possível manipular o while para que, como você mencionou acima, eu consiga atribuir índices para cada linha, durante o momento em que o read entra em ação.
Pelo que entendi não é possível, logo poderia fazer algo assim:


count=0
while read LINE;do
vetor[$count]=$LINE
count=$(( $count + 1 ));
done < file.txt


No entanto, quando o arquivo é muito grande, esse processo demora muito. Por isso que eu queria saber se daria para digamos assim, aproveitar a atribuição de LINE e fazer o while trabalhar com índices. Entendeste??


7. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as c

Paulo
paulo1205

(usa Ubuntu)

Enviado em 05/08/2016 - 04:50h

Permita-me fazer três considerações, antes de prosseguir com a resposta:

- O shell, quando usado como linguagem de programação, não é famoso por ter bom desempenho. Se você quer processar textos, há ferramentas muito melhores (por exemplo, Perl, AWK e, para casos mais simples, até mesmo sed e grep). Houve um tópico aqui na comunidade que deixou isso bem claro (cf. https://www.vivaolinux.com.br/topico/Shell-Script/Como-criar-um-script-para-localizar-varias-palavra...).

- Se o arquivo for realmente MUITO grande, ler para um array em memória pode ser um problema (i.e. gastar toda a memória).

- O shell é muito limitado com relação às operações de entrada e saída que pode realizar.


Você falou em “fazer o while trabalhar com índices”. Não sei se entendi o que você quer saber, por isso vou falar de várias coisas que podem estar um pouco mais ou um pouco menos relacionadas ao efeito que você quer obter.

O comando while não trabalha com índices, porque a única coisa que ele testa é se a condição de controle (no seu caso, o resultado do comando read) é verdadeira ou falsa.

O comando read trata a entrada como uma fila de dados: ele pega os caracteres de cada linha, e nunca pode voltar atrás nem saltar para frente arbitrariamente. Se você quiser saltar para frente (para trás é totalmente impossível), o único jeito é ler e imediatamente desprezar os elementos da fila que não lhe interessam, até passar a quantidade de elementos sobre as quais você queria saltar. Tem de ser assim porque o shell não tem como saber antecipadamente qual o comprimento de cada linha

O Bash tem dois comandos (aparentemente sinônimos) que permitem ler linhas consecutivas diretamente para um array: mapfile e readarray, que inclusive possuem opções que permitem saltar (apenas para frente) dados do arquivo ou iniciar a leitura a partir de uma posição específica do array. Contudo, eu recomendo cautela com esse comando, pois, além do risco de exaurir memória com arquivos muito grandes, tais comandos são incompatíveis com outros sabores de shell (e.g. Bourne Shell tradicional (sh), Korn Shell (ksh, incluindo o ksh93) e as variantes de ambos (dash, ash, pdksh, mksh etc.)).


8. Re: Ao utilizarmos o comando while para ler um arquivo, é possível isolar as linhas manipulando-as c

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 05/08/2016 - 17:17h

Ok Paulo1205, tudo que você disse foi bastante esclarecedor e com certeza me deu muitas ideias, por isso muito obrigado!!

Obrigado a todos que contribuíram também.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts