Alguém poderia explicar como o código a seguir funciona?
echo '1 2 3 4 5 6' | while read a b c
do
echo $c $b $a
done
Especificamente, eu gostaria de saber por que a saída desse loop é 3 4 5 6 2 1
, em vez de 3 2 1
e 6 5 4
em duas linhas separadas? Parece que não consigo entender isso ...
Reescrever o loop dessa maneira revela o que está acontecendo:
Isso fornece, como saída:
Observe primeiro que apenas um único comando de eco é executado. Se fosse executado mais de uma vez, você veria, entre outras coisas, as substrings
(iteration beginning)
e(iteration ending)
impressas mais de uma vez.Isso significa que ter um
while
loop aqui não está realmente conseguindo nada. Oread
builtin lê o texto 1 separado por espaço em branco em cada variável especificada. A entrada extra é anexada ao final da última variável especificada. 2 Assim, variáveisa
eb
assumir os valores1
e2
, respectivamente, enquanto quec
assume o valor3 4 5 6
.Quando a condição do loop (
while read a b c
) é avaliada pela segunda vez, não há mais entrada disponível no canal (nós apenas canalizamos uma única linha de texto); portanto, oread
comando é avaliado como falso em vez de verdadeiro e o loop é interrompido (antes de executar o corpo uma segunda vez).1 : Para ser técnico e específico, o
read
built-in , quando recebe nomes de variáveis como argumentos, lê a entrada, dividindo-a em "palavras" separadas quando encontra o espaço em branco do IFS (consulte também esta pergunta e este artigo ).read
O comportamento do 2 : de obstruir qualquer campo extra de entrada na última variável especificada não é intuitivo para muitos scripts, a princípio. Torna-se mais fácil entender quando você considera que, como diz a resposta de Florian Diesch ,read
sempre (tentará) ler uma linha inteira - e issoread
se destina a ser utilizável com e sem um loop.fonte
while
não servir o seu propósito normal neste exemplo, mas em seguida, oread
comando jogou-me fora ... De alguma forma, eu interpretei-o como "enquantoread a b c
não é falsa, façaecho ...
". Obrigado por explicar como realmente funcionou. Me deparei com este código de ontem e sabia que iria me incomodar até que eu percebi isso ... lolread a b c
avaliado como verdadeiro, e a condição do loop (read a b c
) é executada mais de uma vez. Bit avalia apenas como verdadeiro na 1ª vez. Na segunda vez, não há mais entrada a ser lida no canal, portanto, o final do arquivo é encontrado, causandoread
retorno falso . (Consulte a última seção da saída dehelp read
, em "Status de saída", para obter detalhes, observando que, nos scripts de shell, zero significa verdadeiro e diferente de zero significa falso.) Se você canalizou mais de uma linha de entradawhile read ...
, o corpo do loop seria executado várias vezes.