如何在一个循环中处理每个输出线?

在运行 Grep命令之后,我从一个文件中检索了许多行,如下所示:

var=`grep xyz abc.txt`

假设我得到了10行结果是由 xyz 组成的。

现在我需要处理由 grep 命令得到的每一行。我该怎么做?

226454 次浏览

一种简单的方法是不将输出存储在变量中,而是直接使用 while/read 循环对其进行迭代。

比如:

grep xyz abc.txt | while read -r line ; do
echo "Processing $line"
# your code goes here
done

这个方案有很多变化,这取决于你到底想要什么。

如果需要更改循环内部的变量(并且在循环外部可以看到这种更改) ,可以按照 Fedorqui 的回答中的说明使用进程替换:

while read -r line ; do
echo "Processing $line"
# your code goes here
done < <(grep xyz abc.txt)

您可以执行以下 while read循环,它将由使用所谓的进程替换的 grep命令的结果提供:

while IFS= read -r result
do
#whatever with value $result
done < <(grep "xyz" abc.txt)

这样,您就不必将结果存储在变量中,而是直接将其输出“注入”到循环中。


请注意根据 BashFAQ/001: 如何逐行(和/或逐字段)读取文件(数据流、变量) ?中的建议使用 IFS=read -r:

要读取的-r 选项可以防止反斜杠解释(通常使用 作为反斜杠换行符对,继续多行或 如果没有这个选项,任何未转义的反斜杠 你应该总是使用-r 带读的选项。

在上面的场景中,IFS = 防止修剪前导和尾随 如果你想要这个效果,删除它。

关于工艺替代,在 Bash 黑客主页中有解释:

进程替换是一种重定向形式,其中输入或 进程(某些命令序列)的输出显示为临时的 文件。

我建议在这里使用 awk 而不是 grep + 。

awk '$0~/xyz/{ //your code goes here}' abc.txt

通常处理的顺序并不重要,GNU 并行就是为这种情况设计的:

grep xyz abc.txt | parallel echo do stuff to {}

如果你处理的更像是:

grep xyz abc.txt | myprogram_reading_from_stdin

myprogram是慢的,那么你可以跑:

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

不使用—— line-buffer grep 选项进行任何迭代:

your_command | grep --line-buffered "your search"

现实生活中的例子与 Symfony PHP 框架路由器调试命令输出,以抓取所有“ api”相关的路由:

php bin/console d:r | grep --line-buffered "api"

使用 while/read 循环迭代 grep 结果。 比如:

grep pattern filename.txt | while read -r line ; do
echo "Matched Line:  $line"
# your code goes here
done

对于那些寻找俏皮话的人:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done