如何逐行处理Shell命令的输出?

29

我需要从一个Bash脚本中处理一个库的共享库依赖项。 for 命令逐字逐句地处理:

for DEPENDENCY in `otool -L MyApplication | sed 1d`
do
    ...
done

如何逐行处理结果?


https://mywiki.wooledge.org/DontReadLinesWithFor - tripleee
7个回答

40
你应该使用read命令。
otool -L MyApplication | sed 1d | \
while read i
do
  echo "line: " $i
done

请参阅bashref以了解read内置命令及其选项的描述。您还可以查看以下教程,其中包含使用readfor结合的示例。


11
警告:如果你需要在 while 循环中设置变量(即将 otool 的输出保存起来),那么它们会在循环结束时消失,因为它是管道的一部分,所以运行在子shell 中。在 bash 中,你可以通过稍微调整一下代码来解决这个问题:while read i; do ... done < <(otool -L MyApplication | sed 1d) - Gordon Davisson
2
另一个警告:这将删除许多空格和反斜杠。使用 read -r i 读取行时不进行此类修改。 - Jens
@JamesMorris 不是read -r,而是read会吃掉前后的空格和反斜杠。试试这个命令:printf ' foo\\bar \n'|read a; echo "<$a>",然后再用read -r - Jens
1
@Jens,...在最佳实践调用IFS= read -r i时清除IFS的行为消除了前导和尾随空格修剪。 - Charles Duffy
1
而且,用 { read _; while IFS= read -r i; do echo "line: $i"; done; } 替换 sed 1d | ... 会稍微提高效率 -- 这样我们在管道中就不需要一个额外的可执行文件来启动并循环整个数据流,只需让 bash 自己读取标题到 _ 中,然后将其抛弃,再进入循环即可。 - Charles Duffy
显示剩余7条评论

10
otool -L MyApplication | sed 1d | while read line ;
do
  # do stuff with $line
done

应该使用 while IFS= read -r line 来避免破坏前导/尾随空格或反斜杠。请参见 BashFAQ #1 - Charles Duffy

3
尝试将内部字段分隔符更改为换行符。默认情况下,使用for循环时,bash会通过空格分隔标记。您的IFS设置将使for循环根据等于IFS的任何字符串拆分标记(因此将列表标记按新行而不是按空格拆分)。
[bash ] $ IFS="
"
[bash ] $ for DEPENDENCY in `otool -L MyApplication | sed 1d`
do
    ....
done

2

您需要使用shell内置的read,但需要注意包含空格和制表符的行。我建议本地更改$IFS的值:

 otool -L MyApplication | sed 1d | \
 while IFS= read i; do
     echo "line: $i"
 done

[编辑:采纳Charles的建议]


你目前只在read中更改了IFS,但对于未引用的扩展,它仍保持其先前/默认值。将$iecho中移入引号(echo "line: $i")以避免字符串分割和全局扩展。另请参见I just assigned a variable, but echo $variable shows something else! - Charles Duffy

1

现代的Bash方法:

while read i; do
    ...
done < <(otool -L MyApplication | sed 1d)

注意:上面的两个"<"不是打错了,那是正确的语法。

2
当你使用 while IFS= read -r i; do 时,如果你不清除 IFS,那么前导和尾随的空格将被删除;如果你不使用 -r,则反斜杠会被解释。 - Charles Duffy

0

你也可以使用awk来完成,不需要使用bash的循环

otool -L MyApplication | awk 'NR>1
{
  # do your stuff here since awk process line by line.
}' 

0

您可以使用 awk 在每行的基础上处理事情。最佳方法取决于您要做什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接