正则表达式:为什么这个负向预查不起作用?

6
我有这样的文本
real:: a
real :: b
real c

现在我想匹配那些没有跟随::的实际内容,而在这种情况下,我只想匹配第三个实际内容。因此,我尝试使用具有前瞻性的正则表达式。

real\s*(?!::)

但这个匹配。
real :: b
real c

"

对于\s*表示零个或多个\s,为什么会匹配real :: b

更新:

感谢Wiktor Stribiżew。使用regex101调试工具,我们可以发现回溯使事情变得复杂。

我提出了另一个类似的任务,但是我无法解决它。

"
real (xx(yy)) :: a
real (zz(pp)):: b
real (cc(rr)) c

再次强调,我希望匹配不包含::real (cc(rr))

real\s*\(.*?\)+(?!\s*::)

这是我尝试过的方法,但失败了。请查看正则表达式调试,这也是由于回溯引起的。但如何正确地做到这一点?
1个回答

10
你需要将\s*放入前瞻中:
real(?!\s*::)

请看正则表达式演示

正则表达式real\s*(?!::)匹配real,因为real匹配real,然后\s*匹配0或多个空格,然后向前检查失败了,在::引擎回溯,也就是说,它会释放与\s*匹配的空格,并尝试重新匹配字符串。由于\s*可以匹配一个空字符串,所以:: b前的real被匹配。

请看regex101上的正则表达式调试器方案,展示了背后的运作过程:

enter image description here


好的,但是你能解释一下为什么我的正则表达式失败了吗? - user15964
我添加了解释,为什么前瞻外面的\s*匹配第二种情况,并添加了来自regex101的图表,说明了这个过程。 - Wiktor Stribiżew
1
哇,我之前确实尝试过regex101。但是我错过了调试器工具!非常感谢您展示这个,非常有用! - user15964
嗨,Wiktor Stribiżew。我又遇到了一个问题,你想看看吗? - user15964
几乎要带孩子出去散步了。尝试使用real(?!.*?::)。你必须允许在前瞻中的::之前有0个或多个字符,否则回溯仍然会使匹配不必要的real成为可能。 - Wiktor Stribiżew
显示剩余2条评论

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