PCRE:回溯引用在向后查找中不允许使用?

7
PCRE正则表达式/..(?<=(.)\1)/无法编译:“在反向引用断言中不允许使用子模式引用。”有趣的是,在前瞻中似乎是可以接受的,例如/(?=(.)\1)../,但不适用于后瞻。是否有技术原因导致只有后瞻不允许使用反向引用?

我很好奇,特别是为什么。更奇怪的是,即使 /..(?<=(.)(?=\1).)/ 被接受,而 /..(?<=(.)\1)/ 则不被接受。 - Connor Smith
1
这是因为在后顾模式中不允许使用变长子模式。由于反向引用可以具有任意长度,因此在后顾模式中也不允许使用它。对于pcre,经典的解决方法(如果可能)是使用\K功能。 - Casimir et Hippolyte
这一点并不奇怪。(?<=(.)(?=\1).) 能够工作是因为回溯引用被包含在一个零宽断言(前瞻)中,所以后顾表达式中子模式的长度是固定的。 - Casimir et Hippolyte
1
请注意,在分析模式时,忽略了第1组中子模式具有恒定长度的事实。(明确地说,反向引用=可变长度,仅此而已) - Casimir et Hippolyte
1
@WolfgangKluge .NET是少数几种能够做到这一点的语言之一。我还没有听说过其他“常见”语言能够做到这一点。 - HamZa
显示剩余3条评论
1个回答

3
使用Python的re模块时,即使匹配某些固定长度的字符串,回顾引用在lookbehind中也不被支持。

回顾断言并不完全支持PCRE规则。具体来说,当正则表达式引擎到达回顾断言时,它会尝试确定其大小,然后跳回检查匹配项。

这个大小决定让你做出选择:

  • 允许变量大小,那么每个回顾断言都需要在跳回之前执行
  • 禁止变量大小,那么我们可以直接跳回

由于第一种解决方案对我们(用户)来说是最好的,但显然是最慢和最难开发的。因此,对于PCRE正则表达式,他们决定使用第二种解决方案。例如,Java正则表达式引擎允许半变量回顾:您只需要确定最大大小。


我来到了PCRE和Python的re模块。
我在PCRE文档中没有找到其他内容,只有这个错误代码:

COMPILATION ERROR CODES
25: lookbehind assertion is not fixed length

但在这种情况下,回顾断言固定长度。
现在,我们可以在re文档中找到以下内容:

包含的模式必须仅匹配某些固定长度的字符串,这意味着允许abc或a|b,但不允许a*和a{3,4}。即使匹配某些固定长度的字符串,也不支持组引用。

我们找到了罪犯......如果您想尝试Python的regex模块,它似乎支持可变长度的lookbehind。


你有什么参考资料可以证明你的观点吗?也许从PCRE源代码中摘取一些会更有说服力。 - Wiktor Stribiżew
@stribizhev 我找到了根源,深入文档中。 - zessx

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