175

运行grep命令后,我从文件中检索了许多行,如下所示:

var=`grep xyz abc.txt`

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

现在我需要处理由于 grep 命令而得到的每一行。我该如何进行呢?

4

7 回答 7

315

一种简单的方法不是将输出存储在变量中,而是直接使用 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)
于 2013-05-01T12:23:42.733 回答
23

您可以执行以下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 选项与 read 一起使用。

在上面的场景中, IFS= 防止修剪前导和尾随空格。如果您想要此效果,请将其删除。

关于进程替换,在bash 黑客页面中有说明:

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

于 2013-05-01T12:25:56.790 回答
9

我建议在这里使用 awk 而不是 grep + 其他东西。

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

于 2013-05-01T13:40:00.377 回答
8

对于那些寻找单线的人:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
于 2020-02-18T12:19:18.633 回答
2

无需使用 --line-buffered grep 选项进行任何迭代:

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

带有 Symfony PHP Framework 路由器调试命令输出的真实示例,用于 grep 所有“api”相关路由:

php bin/console d:r | grep --line-buffered "api"
于 2019-09-21T11:00:20.417 回答
1

使用 while/read 循环遍历 grep 结果。喜欢:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done
于 2019-09-30T09:34:59.560 回答
0

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

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
于 2018-12-01T01:26:58.037 回答