PHP正则表达式:负向回顾后发现中的反向引用替代方案

5

我希望找到一个被捕获的组在字符串后面不再出现的实例:

aaaBbb  = CccBbb  <- format is valid, skip
aaaDddd = CccDddd <- format is valid, skip
aaaEeee = CccFfff <- format is not valid, match this one only

所以这个正则表达式匹配了我不想匹配的行(https://regex101.com/r/lon87L/1)。

/^ +\w+([A-Z][a-z+]) += +\w+\1$/mg

我在https://www.regular-expressions.info/refadv.html上读到,PHP不支持负向回顾后引用,但其他正则表达式实现可以。因此,像这样的内容会匹配我想要匹配的无效行,但在PHP中不起作用:

/^ +\w+([A-Z][a-z+]) += +\w+(?<!\1)$/mg

除了在 PHP 中匹配所有三行并通过 foreach 循环遍历匹配项之外,还有其他可行的方法吗?


负回顾需要编译时固定长度。反向引用是具有可变长度的运行时项。一种选择是使用(?>\1(*SKIP)(*FAIL)|\w)+并匹配反向引用。这可能更快。 - user557597
你可以在这里查看 https://regex101.com/r/6gfSBi/1 顺便说一下,只有Dot-Net引擎支持可变宽度的后顾断言(包括反向引用)。 - user557597
如果它必须在 EOS 处,只需在反向引用后添加 $。https://regex101.com/r/QuXJLY/1 - user557597
2个回答

2
尝试使用负向前瞻而不是负向后顾。它同样有效,并且可以在PHP中使用。
^ +\w+([A-Z][a-z]+) += +(?!\w+\1).*$

正则表达式101演示

PHP演示


1

一种选择是,在每个重复的=后面的\w之前,使用否定前瞻来匹配\1$

^ +\w+([A-Z][a-z]+) += +(?:(?!\1$)\w)+$
                        ^^^^^^^^^^^^^^

https://regex101.com/r/lon87L/2

但这只会排除掉在字符串末尾出现的反向引用。如果你想确保之前匹配的短语不会出现在最后的\w中的任何地方,只需从重复组内移除$即可:
^ +\w+([A-Z][a-z]+) += +(?:(?!\1)\w)+$
                                ^

https://regex101.com/r/lon87L/3


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接