如何一次grep两种模式

How to grep two patterns at once

很多时候我不得不这样做命令行的事情,我通过管道连接到 grep 并希望匹配两个不同的表达式。 ( OR 匹配 A OR B。)

例如,我想为 foo[0-9]+ 或 bar[0-9]+ grep generate_out 的输出。我当然可以只执行两次:

generate_out| grep "foo[0-9]+"   
generate_out| grep "bar[0-9]+"   

但通常 generate_out 很昂贵,我不想 运行 它两次(或存储它的输出)。相反,我只想使用一个表达式:

generate_out| grep "foo[0-9]+ OR bar[0-9]+"   

当然这行不通,但我想要等效的表达式。

在你的正则表达式中使用交替:

generate_out | grep -E '(foo|bar)[0-9]+'

-E 的使用启用了 ERE 功能,这是其中之一。 (默认情况下,grep 仅支持 BRE;BRE 的某些实现——例如 GNU 的——可能具有启用 ERE 功能的特殊语法;在 GNU 情况下,BRE 中的 \| 等同于 | ERE;但是,依赖此类扩展而不是正确打开 ERE 是不可移植的。


egrepgrep -E 的向后兼容同义词;然而,only the latter is specified as a requirement by POSIX.

为简单起见,使用 awk:

generate_out| awk '/foo[0-9]+/ || /bar[0-9]+/'

在这种特殊情况下当然可以简化为:

generate_out| awk '/(foo|bar)[0-9]+/'

但一般来说,您希望将 awk 用于简单、一致的 ORAND 正则表达式:

cmd | grep -E 'foo.*bar|bar.*foo'
cmd | awk '/foo/ && /bar/'

cmd | grep 'foo' | grep -v 'bar'
cmd | awk '/foo/ && !/bar/'

cmd | grep -E 'foo|bar'
cmd | awk '/foo/ || /bar/'      (or awk '/foo|bar/')

cmd | grep -E 'foo|bar' | grep -E -v 'foo.*bar|bar.*foo'
cmd | awk '(/foo/ && !/bar/) || (/bar/ && !/foo/)'

使用 grep 的 -e 选项指定多个模式 "OR'ed":

$ seq 15 | grep -e 5 -e 3
3
5
13
15