Reescrevendo o loop dessa maneira revela o que está acontecendo:
echo '1 2 3 4 5 6' | while read a b c
do
echo '(iteration beginning)' a="$a" b="$b" c="$c" '(iteration ending)'
done
Isso fornece, como saída:
(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)
Observe primeiro que apenas um único comando echo é executado. Se ele 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 loop while aqui não está realmente realizando nada. O read builtin lê o texto separado por espaço em branco 1 em cada variável especificada. A entrada extra é anexada ao final da última variável especificada. 2 Assim, as variáveis a e b assumem os valores 1 e 2 respectivamente, enquanto c assume o valor 3 4 5 6 .
Quando a condição de loop ( while read a b c ) é avaliada pela segunda vez, não há mais entrada disponível do pipe (nós apenas canalizamos uma única linha de texto), então o comando read é avaliado como falso em vez de true e o loop pára (antes de executar o corpo uma segunda vez).
1 : Para ser técnico e específico, o read builtin , quando passou nomes de variáveis como argumentos, lê a entrada, dividindo-o em "palavras" separadas quando encontrar espaços em branco IFS (ver também esta questão e este artigo ).
2 : O comportamento de read de bloquear qualquer campo extra de entrada na última variável especificada não é intuitivo para muitos criadores de scripts, no início. Torna-se mais fácil entender quando você considera que como a resposta de Florian Diesch diz , read será sempre (tente) uma linha inteira - e que read se destina a ser utilizável com e sem loop.