Переписав цикл таким образом, вы узнаете, что происходит:
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
Это дает в качестве вывода:
(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)
Сначала обратите внимание, что выполняется только одна команда echo. Если бы это было работать более чем один раз, вы, помимо всего прочего, увидеть (iteration beginning)и (iteration ending)подстроки напечатанных более чем один раз.
Это значит, что наличие whileпетли здесь ничего не значит. readВстроенный читает разделенных пробелами текст 1 в каждой заданной переменной. Дополнительный ввод добавляется в конец последней указанной переменной. 2 Таким образом, переменные aи bпринимают значения 1и, 2соответственно, cпринимают значения 3 4 5 6.
Когда условие цикла ( while read a b c) вычисляется во второй раз, из канала больше нет входных данных (мы передали ему только одну строку текста), поэтому readкоманда оценивается как ложь вместо истины, и цикл останавливается (перед выполнением кузов второй раз).
1 : Чтобы быть техничная, встроенной , при передаче имен переменных в качестве аргументов, считывает информацию, разделив его на отдельные «слова» , когда он встречает IFS пробельные (смотри также этот вопрос и в этой статье ).read
2 : readповедение заклинивания любых дополнительных полей ввода в последней указанной переменной, на первый взгляд, неинтуитивно для многих сценариев. Понять это становится легче, если учесть, что, как говорится в ответе Флориана Диша , readон всегда будет (пытаться) прочитать целую строку - и это readпредназначено для использования как с циклом, так и без него.