在linux脚本中使用“while read …”
有人可以解释下面的代码如何工作?
echo '1 2 3 4 5 6' | while read abc do echo $c $b $a done
具体来说,我想知道为什么这个循环的输出是3 4 5 6 2 1
,而不是3 2 1
和6 5 4
在两条独立的线上? 我好像无法绕过它…
read
从标准输入读取整行,将行拆分为字段并将此字段分配给给定变量。 如果有多个部分而不是变量,则将剩余的部分分配给最后一个变量。
在你的情况下, $a
被分配1
, $b
被分配2
, $c
被分配$c
3 4 5 6
。
以这种方式重写循环揭示了发生的事情:
echo '1 2 3 4 5 6' | while read abc 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
这里有一个while
循环并没有真正完成任何事情。 read
builtin将以空格分隔的文本1读入每个指定的变量。 额外输入将附加到指定的最后一个变量的末尾。 2因此,变量a
和b
分别取值1
和2
,而c
取值3 4 5 6
。
当第二次评估循环条件( while read abc
)时,管道中没有更多可用输入(我们只将其输入单行文本),因此read
命令的计算结果为false而不是true ,循环停止(在第二次执行身体之前)。
1 :为了技术和特定, read
builtin在将变量名称作为参数传递时读取输入,在遇到IFS空格时将其拆分为单独的“单词” (另请参阅此问题和本文 )。
2 : read
将任何额外的输入字段干扰到指定的最后一个变量的行为首先对许多脚本编写者来说是非直观的。 当您考虑到这一点时,您会更容易理解, 正如Florian Diesch的回答所说 , read
将始终(尝试)读取整行 – 并且该read
旨在可用于循环和不循环。