有人可以解释一下下面的代码是如何工作的吗?
echo '1 2 3 4 5 6' | while read a b c
do
echo $c $b $a
done
具体来说,我想知道为什么这个循环的输出是3 4 5 6 2 1
,而不是3 2 1
和6 5 4
在两条单独的行上?我似乎无法理解它……
答案1
read
从标准输入读取整行,将该行拆分为字段并将这些字段分配给给定的变量。如果分片数多于变量数,则将剩余分片分配给最后一个变量。
在您的情况下$a
已分配1
,$b
已分配2
,$c
其余的3 4 5 6
。
答案2
通过这种方式重写循环可以揭示正在发生的事情:
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: 从技术角度和具体角度来说,内置read
当传递变量名作为参数时,读取输入,将其拆分成单独的“单词”当它遇到IFS 空格(也可以看看这个问题和本文)。
2:read
将任何额外的输入字段塞入最后一个指定的变量的行为对于许多脚本编写者来说一开始是不直观的。当你考虑到以下情况时,就会变得更容易理解:正如 Florian Diesch 的回答所说,read
将始终(尝试)读取整行 - 并且read
可以在有循环和无循环的情况下使用。