如何根据特定模式对行进行grep?


8

假设我有一个包含以下两行的文件:

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

我只需要获得包含模式的行/aa/bbbb/cccccc,就不需要包含额外字符的第二行,即?dddddddd。现在当我尝试

grep '/aa/bbbb/cccccc' file

然后两条线都被选中。我需要完整的行,因此grep -o无法解决。

使用grep以便基于搜索模式仅选择第一行的可能解决方案是什么?

Answers:


7

请尝试以下使用-PPerl-regexp)参数的grep命令。

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)这种否定的后向断言,在字符串之前的字符/aa/bbbb/cccccc将是任何字符,但不能是非空格字符。

  • (?!\S) 负向超前断言,匹配后的字符将是任何字符,但不能是非空格字符。

另一个grep,

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

通过python,

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

将上述代码保存在文件中,并将其命名为script.py。然后执行以下脚本

python3 script.py /path/to/the/file/you/want/to/work/with

谢啦。顺便说一句,可以使用普通/扩展正则表达式而不是perl正则表达式来完成此操作吗?
heemayl 2014年

1
像terdon贴,你可以简单地grep '/aa/bbbb/cccccc ' file
阿维纳什·拉吉

但是上面不会打印只有/aa/bbbb/cccccc字符串的行。
Avinash Raj 2014年

您也可以将其与grep -E '/aa/bbbb/cccccc(\s+|$)' file
terdon

是的,像这样grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Avinash Raj

10

最简单的方法是在模式后添加一个空格:

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

或者,为了匹配各种空白:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

要么

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

或者,以积极的前瞻性

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

或者,以负前瞻

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

或者您可以撤消比赛:

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

或者,也要匹配仅包含您的模式(不包含尾随空格)的行:

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

或者,您可以只使用一个小脚本:

  • 在awk中:

    $ awk '$3=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    或者,如果您不知道您的模式在哪个字段中

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • 在Perl中

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

@terdon grep -v 'c?' file为什么不使用grep -v '?' file文件,因为文件只有两行。
αғsнιη

@KasiyA是的,我只是想保留一些模式。不过,在这种情况下,您说的很对,grep -v '?'就足够了。
terdon 2014年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.