为什么这种负面回顾被认为是成功的正则表达式匹配?

Why is this negative lookbehind being considered a successful regex match?

我希望这个简单的文本字符串不会被视为匹配项:

xyz@xyz:~$ echo xy | perl -n -e 'print if /y(?<!x)/'
xy

但奇怪的是。我也试过 @ https://regex101.com/ 结果是一样的。它似乎会匹配 y,这让我很困惑。如果我的理解是正确的,上面的正则表达式应该只匹配 ys 是 而不是 前面有 x.

PS:我举了一个简单的例子。一般来说,我想使用负向后查找来匹配完整的字符串,而不一定是单个字符,例如 x.

我正在使用 Perl 正则表达式风格。

谢谢

您将否定回溯断言的位置向后。

它是零宽度,所以需要像你写的那样在 y 前面。

给定:

$ echo $'xy\nay\nyx' 
xy
ay
yx

lookbehind /y(?<!x)/ 匹配 y 前面或后面带有 x 的行,因为 y 在断言后面(不是 x):

$ echo $'xy\nay\nyx' | perl -n -e 'print if /y(?<!x)/'
xy
ay
yx

请注意 yx 也匹配,因为断言出现在 x 之前并且正在查看 y 所以所有三行都是匹配的。

Vs你要找的是:

$ echo $'xy\nay\nyx' | perl -n -e 'print if /(?<!x)y/'
ay
yx

Demo

Further explanation.

或者,如果通过在断言中包含 y 向后看 y,则需要考虑 y 的宽度(或任何匹配):

$ echo $'xy\nay\nyx' | perl -n -e 'print if /y(?<!xy)/'
ay
yx

ab 表示 a 后跟 b。因此,您正在检查一个位置的 y,然后检查下一个位置前面是否没有 x。 它前面没有 x——它前面有 y——所以模式匹配。

你想要

/(?<!x)y/

/(?:^|[^x])y/