这个案例:
$ cat t01.txt
xxxyyyzzz
$ cat t01.txt | grep -Po '(?<=xxx).*(?=zzz)'
结果是:
yyy
这是预期的。
然而,这个案例:
$ cat t02.txt
xxx
yyy
zzz
$ cat t02.txt | grep -Pzo '(?<=xxx).*(?=zzz)'
结果是:
<nothing>
这是出乎意料的。
为什么以及如何解决?
答案1
因为默认情况下,.
与 Perl 正则表达式中的换行符不匹配。您需要显式匹配它,或者使用s
正则表达式的标志:
$ < t02.txt grep -Pzo '(?<=xxx\n).*\n(?=zzz)'
yyy
$ < t02.txt grep -Pzo '(?s)(?<=xxx).*(?=zzz)'
yyy
参见例如perlre
手册页:
在“元字符”部分:
. Match any single character except newline Not in [] (under /s, includes newline)
并在“修饰符”中:
s
将字符串视为单行。也就是说,更改"."
为匹配任何字符,甚至是换行符,通常它不会匹配。
答案2
这实际上是预期的行为。.
包括除换行符之外的任何字符。您正在寻找的正则表达式是:
(?<=xxx)\n*.*\n*(?=zzz)
这是一个测试正则表达式的好网站,它也对它的每个部分都有解释,所以你总是知道它为什么会这样:https://regex101.com