Rewriting the loop this way reveals what is happening:
echo '1 2 3 4 5 6' | while read a b c
echo '(iteration beginning)' a="$a" b="$b" c="$c" '(iteration ending)'
This gives, as its output:
(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)
Notice first that only a single echo command is run. If it were run more than once, you would, among other things, see the
(iteration beginning) and
(iteration ending) substrings printed more than once.
This is to say that having a
while loop here is not really accomplishing anything. The
read builtin reads whitespace-separated text1 into each specified variable. Extra input gets appended to the end of the last variable specified.2 Thus variables
b take on the values
2 respectively, while
c takes on the value
3 4 5 6.
When the loop condition (
while read a b c) is evaluated the second time, there's no more input available from the pipe (we only piped it a single line of text), so the
read command evaluates to false instead of true and the loop stops (before ever executing the body a second time).
1: To be technical and specific, the
read builtin, when passed variable names as arguments, reads input, splitting it into separate "words" when it encounters IFS whitespace (see also this question and this article).
read's behavior of jamming any extra fields of input into the last variable specified is nonintuitive to many scripters, at first. It becomes easier to understand when you consider that, as Florian Diesch's answer says,
read will always (try to) read a whole line--and that
read is intended to be usable both with and without a loop.