我想知道是否有一种方法可以组合一系列 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)
您不能将过滤器grep a | grep c | grep -v d转换为单个简单的grep. 只有复杂和无效的方法。结果性能缓慢,表达式的含义模糊不清。
如果您只想运行单个命令,您也可以使用awkwhich 与正则表达式一起使用,并且可以将它们与逻辑运算符结合使用。这相当于您的过滤器:
awk '/a/ && /c/ && $0 !~ /d/'
Run Code Online (Sandbox Code Playgroud)
我认为在大多数情况下,没有理由将管道简化为单个命令,除非组合导致真正简单的 grep 表达式可能更快(请参阅下面的结果)。
类 Unix 系统旨在使用管道并将各种实用程序连接在一起。虽然管道通信不是最有效的,但在大多数情况下它已经足够了。因为现在大多数新计算机都有多个 CPU 内核,您可以“自然地”通过使用管道来利用 CPU 并行化!
您原来的过滤器工作得很好,我认为在许多情况下,awk即使在单核上,解决方案也会慢一点。
使用简单的程序我已经产生具有200条000 000线的随机测试文件,每个具有4个字符作为从字符的随机组合a,b,c和d。该文件有 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|没有性能损失。
| 归档时间: |
|
| 查看次数: |
34707 次 |
| 最近记录: |