运行grep命令后,我从文件中检索了许多行,如下所示:
var=`grep xyz abc.txt`
假设我得到了 10 行,结果由 xyz 组成。
现在我需要处理由于 grep 命令而得到的每一行。我该如何进行呢?
一种简单的方法不是将输出存储在变量中,而是直接使用 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 选项与 read 一起使用。
在上面的场景中, IFS= 防止修剪前导和尾随空格。如果您想要此效果,请将其删除。
关于进程替换,在bash 黑客页面中有说明:
进程替换是一种重定向形式,其中进程的输入或输出(某些命令序列)显示为临时文件。
我建议在这里使用 awk 而不是 grep + 其他东西。
awk '$0~/xyz/{ //your code goes here}' abc.txt
对于那些寻找单线的人:
grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
无需使用 --line-buffered grep 选项进行任何迭代:
your_command | grep --line-buffered "your search"
带有 Symfony PHP Framework 路由器调试命令输出的真实示例,用于 grep 所有“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
通常处理的顺序并不重要。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