如何处理由于grep命令而收到的每一行


152

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

var=`grep xyz abc.txt`

假设我得到了10条包含xyz的行。

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


6
这里没有答案提到grep -o这种事情的力量。该-o标志将返回匹配的文本,每行输出一个匹配项。(这并不详尽,因此echo aaa |grep 'a*'只给您“ aaa”,并省略了三个部分匹配项“”,“ a”和“ aa”)
Adam Katz

Answers:


269

一种简单的方法是不将输出存储在变量中,而是通过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)

如果与xyz没有联系?
XYZ_Linux 2013年

然后什么也没有发生,循环没有运行。
Mat

13
这种方法的问题是(由于管道的原因)循环内的所有内容都在子外壳中,因此设置在循环期间在循环外定义的变量不会使其值在循环后可用!
David Doria 2014年

3
@David:提供了解决您所关注问题的替代方法。(fedorqui已经解决它。)

对于最后一行输出未以换行符终止的命令,您需要:(while read p || [[ -n $p ]]; do ...stackoverflow.com/questions/1521462/…借用)
Ohad Schneider

21

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

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

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


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

读取的-r选项可防止反斜杠解释(通常用作反斜杠换行符,可在多行上继续或转义定界符)。如果没有此选项,则输入中任何未转义的反斜杠将被丢弃。您几乎应该始终将-r选项与read结合使用。

在上述情况下,IFS =可防止修剪前导和尾随空白。如果需要此效果,请将其删除。

关于进程替换,在bash黑客页面中进行了解释:

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


好的,我点击了for版本。试图"${$(grep xyz abc.txt)[@]}"像在stackoverflow.com/a/14588210/1983854中那样做一个循环,但是不能。所以我只保留第一个版本。
fedorqui'SO停止伤害

1
您不能将参数扩展应用于命令替换(除非您使用zsh,在这种嵌套可能起作用的地方)。
13年

这种习惯用法的一个可能问题是,如果循环中的任何内容尝试从标准输入中读取,它将获取文件的一部分。为了避免这种可能性,我喜欢通过文件描述符3而不是stdin发送文件。只需使用while IFS= read -r result <&3done 3< <(grep ...
戈登戴维森


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"

如果your_command是长时间运行的(例如tail -f some.log,就我而言),
唯一可行的

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

0

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

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

0

对于那些寻找一线客的人:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
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.