如何将一系列通过管道连接在一起的 grep 语句组合成一个 grep 语句?

Kei*_*lds 7 grep

我想知道是否有一种方法可以组合一系列 grep 语句,其效果是“和”表达式而不是“或”匹配表达式。

演示如下:

./script  
     From one grep statement, I want output like this
a b c

     not like this
a
c
a b
a b c
a b c d
Run Code Online (Sandbox Code Playgroud)

听说是看剧本。

 #!/bin/bash
 string="a
 b
 c
 d
 a b
 a b c
 a b c d"

 echo -e "\t From one grep statement I want output like this"
 echo "$string" |
 grep a |grep c |grep -v d #Correct output but pipes three grep statements

 echo -e "\n\tNot like this"
 echo "$string" |
 grep -e'a' -e'c' -e-v'd' #One grep statement but matching expressions are "or" versus "and"
Run Code Online (Sandbox Code Playgroud)

pab*_*ouk 8

您不能将过滤器grep a | grep c | grep -v d转换为单个简单的grep. 只有复杂和无效的方法。结果性能缓慢,表达式的含义模糊不清。

三个 grep 的单个命令组合

如果您只想运行单个命令,您也可以使用awkwhich 与正则表达式一起使用,并且可以将它们与逻辑运算符结合使用。这相当于您的过滤器:

awk '/a/ && /c/ && $0 !~ /d/'
Run Code Online (Sandbox Code Playgroud)

我认为在大多数情况下,没有理由将管道简化为单个命令,除非组合导致真正简单的 grep 表达式可能更快(请参阅下面的结果)。

类 Unix 系统旨在使用管道并将各种实用程序连接在一起。虽然管道通信不是最有效的,但在大多数情况下它已经足够了。因为现在大多数新计算机都有多个 CPU 内核,您可以“自然地”通过使用管道来利用 CPU 并行化!

您原来的过滤器工作得很好,我认为在许多情况下,awk即使在单核上,解决方案也会慢一点。

性能对比

使用简单的程序我已经产生具有200条000 000线的随机测试文件,每个具有4个字符作为从字符的随机组合abcd。该文件有 1 GB。在测试期间,它完全加载到缓存中,因此没有磁盘操作影响性能测量。测试在英特尔双核上运行。

单个grep

$ time ( grep -E '^[^d]*a[^d]*c[^d]*$|^[^d]*c[^d]*a[^d]*$' testfile >/dev/null )
real    3m2.752s
user    3m2.411s
sys 0m0.252s
Run Code Online (Sandbox Code Playgroud)

单 awk

$ time ( awk '/a/ && /c/ && $0 !~ /d/' testfile >/dev/null )
real    0m54.088s
user    0m53.755s
sys 0m0.304s
Run Code Online (Sandbox Code Playgroud)

原来的三个 grep 管道

$ time ( grep a testfile | grep c | grep -v d >/dev/null )
real    0m28.794s
user    0m52.715s
sys 0m1.072s
Run Code Online (Sandbox Code Playgroud)

混合 - 正 grep 组合,负管道

$ time ( grep -E 'a.*c|c.*a' testfile | grep -v d >/dev/null )
real    0m15.838s
user    0m24.998s
sys 0m0.676s
Run Code Online (Sandbox Code Playgroud)

在这里你看到grep由于复杂的表达,single很慢。由于良好的并行化,三个 grep 的原始管道非常快。如果没有并行化 - 在单个核心上 - 原始管道的运行速度略快于awk单个进程未并行化的速度。awk 和 grep 可能使用相同的正则表达式代码,并且两种解决方案的逻辑相似。

明显的赢家是组合两个正 grep 并将负一个留在管道中的 hybring。似乎正则表达式 with|没有性能损失。