很可能你的问题在于GNU grep中的
z
标志,该标志将行的定义更改为以
\0
结尾。
很容易演示。例如:
$ echo "$txt"
line 1
line 2
line 3
line 4
line 5
word ...other text
phrase ...yet another text
line 6
line 7
line 8
line 9
line 10
您可以做以下事情:
$ echo "$txt" | ggrep --context=2 -Pz "word|phrase"
或者:
$ echo "$txt" | ggrep --context=2 -P "word|phrase"
line 4
line 5
word ...other text
phrase ...yet another text
line 6
line 7
您可以通过实际在行末添加NUL终止符来证明它可以与
z
一起使用。
$ echo "$txt" | tr '\n' '\0' | ggrep --context=2 -Pz "word|phrase" | tr '\0' '\n'
line 4
line 5
word ...other text
phrase ...yet another text
line 6
line 7
对于Perl正则表达式和before、after以及多行逻辑,您最好使用
Perl!
给定:
$ cat file
line 1
line 2
line 3
line 4
line 5
word ...other text
betweener 1, line 7
betweener 2, line 8
phrase ...yet another text
line 10
line 11
line 12
line 13
line 14
您可以做以下事情:
$ perl -lne 'BEGIN{$b=2; $a=2;}
print join("\n", @a) if (/word/);
print if (/word/../phrase/) || ($c && $c--);
$c=$b if (/phrase/);
shift @a if push(@a, $_)>$a;' file
或者,您也可以使用 POSIX 或 GNU awk:
$ awk 'BEGIN{b=2; a=2}
/word/ { for (i=FNR-b;i<=FNR-1;i++)
print arr[i] # print the lines before the first match
f=1} # flag we are in the match
f || (c && c--) # print either if in the match or tail context
/phrase/ {f=0; c=a} # end match, start tail
{for (ln in arr)
if (ln<FNR-b) delete arr[ln] # rolling line buffer
arr[FNR]=$0} # save current line
' file
要么打印:
line 4
line 5
word ...other text
betweener 1, line 7
betweener 2, line 8
phrase ...yet another text
line 10
line 11
即使没有“中间”行也可以工作。
-z
,所以你的“行”必须以\0
结尾。 - dawg