在Linux脚本中使用“边读边……”


34

有人可以解释下面的代码如何工作吗?

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 16 5 4两个单独的行?我似乎无法全神贯注于此...

Answers:


41

read从标准输入读取整行,将行拆分为字段,并将该字段分配给给定的变量。如果片段多于变量,则剩余片段将分配给最后一个变量。

在你的情况$a分配1$b分配2$c剩余3 4 5 6


谢谢弗洛里安!现在这很有意义...由于某种原因,我认为空格会限制每个变量的读取,但显然不是。我感谢您的帮助!!
linuxgringo 2015年

24

用这种方式重写循环可以揭示正在发生的事情:

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因此变量ab取上的值12分别,而c对值取3 4 5 6

while read a b c第二次评估循环条件()时,管道中没有更多可用的输入(我们仅将其通过管道传输到一行文本中),因此该read命令的计算结果为false而不是true,并且循环停止(在执行身体第二次)。

1:要技术和具体,read内置,当传递的变量名作为参数,读取输入,分割成独立的“词”,当它遇到IFS空白(见这个问题这篇文章)。

2:首先read,将输入的任何额外字段塞入指定的最后一个变量的行为对许多脚本编写者而言并不直观。正如Florian Diesch的回答所说,当您认为这read将始终(尝试)读取整行时,将变得更容易理解,并且该read意图可在有循环或无循环的情况下使用。


Eliah,感谢您抽出宝贵时间解释所有细节。我怀疑,while没有发挥其正常的宗旨在这个例子中,但随后的read命令扔我......不知怎的,我的解读是,“虽然read a b c不假,做echo ...”。感谢您解释它是如何工作的。昨天我遇到了这段代码,并且知道在我弄明白之前它会
困扰

@linuxgringo实际上,每次执行循环主体时每次read a b c求值为true时,循环条件(read a b c)都会运行多次。该位仅在第一时间评估为。第二次,没有更多的输入要从管道读取,因此遇到文件结尾,导致read返回false。(有关help read详细信息,请参见输出的最后部分,“退出状态”,注意,在shell脚本中,零表示true,非零表示false。)如果将输入的多行传递给while read ...,则循环主体将被执行多次。
伊利亚·卡根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.