假设我有一个包含以下两行的文件:
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那么是否只根据搜索模式选择第一行?
答案1
最简单的方法是在模式后添加一个空格:
$ 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
答案2
尝试使用下面的 grep 命令-P
(Perl 正则表达式) 范围。
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
答案3
补充@AvinashRaj的回答,您也可以使用这样的命令。
grep -P '/a+/b+/c+(?!\S)' file