在 linux 脚本中使用“while read...”

lin*_*ngo 36 bash scripts

有人可以解释以下代码的工作原理吗?

echo '1 2 3 4 5 6' | while read a b c
do
  echo $c $b $a
done
Run Code Online (Sandbox Code Playgroud)

具体来说,我想知道为什么这个循环的输出是3 4 5 6 2 1, 而不是3 2 16 5 4在两个单独的行上?我似乎无法围绕它...

Flo*_*sch 43

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

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


Eli*_*gan 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
Run Code Online (Sandbox Code Playgroud)

这给出,作为它的输出:

(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)
Run Code Online (Sandbox Code Playgroud)

首先请注意,只运行了一个 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空白(见这个问题这篇文章)。

2read起初,将任何额外输入字段塞入指定的最后一个变量的行为对许多脚本编写者来说是不直观的。当您考虑到这一点时,就更容易理解了,正如 Florian Diesch 的回答所说read将始终(尝试)阅读整行 - 并且这read旨在在有循环和没有循环的情况下都可用。