使用“grep”查找以任意顺序包含所有三个指定字符的行

use*_*848 10 grep text-processing

我们有一个包含行的文档,我们必须找出 [a|b|c] 是否在每一行中至少出现一次,无论是什么顺序。

例如:

输入:

abc
bca
cab
hhfdhdhfabjfdjdjff
acjfdjdfjdf
fhfhfhfabcjdfjdjfk
ahfhfbkjfjdjffc
Run Code Online (Sandbox Code Playgroud)

所需的输出(第四行不存在,因为它只包含aandb但没有c):

abc
bca
cab
fhfhfhfabcjdfjdjfk
ahfhfbkjfjdjffc
Run Code Online (Sandbox Code Playgroud)

我们正在使用Linux。

mur*_*uru 25

管它:

grep a file | grep b | grep c
Run Code Online (Sandbox Code Playgroud)

  • 我对下面复杂的解决方案感到惊讶。对于任何了解 grep 的人来说,这应该是一个显而易见的答案。 (4认同)

Cos*_*tas 8

在这样的例子sedgrep很容易看到的优点

sed -n '/a/{/b/{/c/p;};}' file
Run Code Online (Sandbox Code Playgroud)

或者:

sed '/a/!d;/b/!d;/c/!d' file
Run Code Online (Sandbox Code Playgroud)


小智 7

让我们比较所有建议的解决方案!

我有一个test.txt大小约 230M的文本文件。我在 Mac Mini 上,更新到 10.10。

1)awk解决方案通过Hauke Laging(最好不要...):

$ time bash -c "awk '/a/ && /b/ && /c/' >> /dev/null"
19.51 real        19.23 user         0.20 sys
Run Code Online (Sandbox Code Playgroud)

2)grepRaghuraman RHauke Laging "bruteforced" (更好,但不是真的......):

$ time bash -c "grep -e 'a.*b.*c' -e 'a.*c.*b' -e 'b.*a.*c' -e 'b.*c.*a' -e 'c.*a.*b' -e 'c.*b.*a' test.txt >> /dev/null"
10.02 real         9.93 user         0.07 sys
Run Code Online (Sandbox Code Playgroud)

3)被muru链接grep起来(好吧!):

$ time bash -c "grep a test.txt | grep b | grep c >> /dev/null"
1.61 real         3.08 user         0.29 sys
Run Code Online (Sandbox Code Playgroud)

4)perl解决方案通过terdon(甚至更好)!

$ time bash -c "perl -ne 'print if /a/ && /b/ && /c/' test.txt >> /dev/null"
0.83 real         0.75 user         0.07 sys
Run Code Online (Sandbox Code Playgroud)

所以,我认为“chained grep”是可以的,但你也可以使用 Perl 来获得更好的性能。我无法测试sed方法,因为 Costas 提供的程序在 mac os 控制台中无法“按原样”运行。

顺便说一句,我不是基准测试专家,如果我做错了什么,抱歉。

  • @dragn 我建议您为所有建议的解决方案添加积分。例如,你目前只说“4)`perl`”,说“4)[terndon](http://unix.stackexchange.com/users/22222/terdon)的[`perl`解决方案](http: //unix.stackexchange.com/a/182922)”。 (3认同)
  • 这个答案正在 [讨论元](http://meta.unix.stackexchange.com/questions/3379/are-answers-comparing-existing-answers-acceptable)。 (2认同)

Hau*_*ing 6

awk '/a/ && /b/ && /c/' file
Run Code Online (Sandbox Code Playgroud)

或者使用 grep (虽然不能很好地扩展):

grep -e 'a.*b.*c' -e 'a.*c.*b' -e 'b.*a.*c' -e 'b.*c.*a' -e 'c.*a.*b' -e 'c.*b.*a'  file
Run Code Online (Sandbox Code Playgroud)


Avi*_*Raj 5

通过grep它接受-PPerl-regexp)参数。

$ grep -P '^(?=.*a)(?=.*b)(?=.*c)' file
abc
bca
cab
fhfhfhfabcjdfjdjfk
ahfhfbkjfjdjffc
Run Code Online (Sandbox Code Playgroud)

解释:

  • ^ 匹配一行的开始
  • (?=.*a) 仅当要匹配的字符串必须包含字母时 a
  • (?=.*b) 必须包含 b
  • (?=.*c) 必须包含 c


归档时间:

查看次数:

11654 次

最近记录:

10 年,7 月 前