PCRE和PCRE2之间的正则表达式差异

15

我们正在考虑将内部正则表达式引擎从PCRE更换为PCRE2。只有正则表达式语法暴露给用户,因此库API的差异对我们的使用不构成问题。但是,我们必须记录任何行为变化。

许多网站讨论API差异,但我没有找到任何列出正则表达式中实际差异的网站。虽然我知道在PCRE中[\w-_][\w\-_]相同,但在PCRE2中无效,我怀疑还存在其他差异。

PCRE2与PCRE的正则表达式有哪些差异?


1
还有:递归不再是原子的,\K 在环视内的行为。 - Casimir et Hippolyte
1
现在需要更多关注,因为GNU grep 3.8(通过-P)和PHP 7.3已经从PCRE转移到PCRE2。 - Adam Katz
我能找到的最好的资源来回答这个问题是PCRE2更改日志(10.00,最早的条目,标记了初始PCRE2发布)和pcre2compat手册页,它描述了PCRE2和Perl引擎之间的差异。 - Adam Katz
@AdamKatz 好的,那么就需要有人将这些来源的差异进行编译,并在此处回答;这样我们就会拥有一个真正有用的SO资源。 - Adám
是的,那也是我的想法,不过最好能找到一份列出 Perl 和 PCRE 差异的文档。还需要进行一些调试工作以查找 PCRE→PCRE2 的差异,因为它们(理论上)比 Perl→PCRE2 的差异要小。 - Adam Katz
1个回答

14

PCRE v8.36和PCRE2 10.39之间的编译差异

我已经编制了一份变更列表,这些变更可能是将pcre转换为pcre2时可能遇到的问题。我已经排除了各种溢出、下溢、分段违规和模式在pcre中可能遇到的各种错误。

Pcre2有一个版本检查模式。您可以使用/(?(VERSION>=10)yes|no)/与"yesno"匹配来检查应用程序的版本。

可能会导致破坏性变化:

  • 模式如/()a/未能设置“第一个字符必须是'a'”信息。例如/(?:(?=.)|(?<!x))a/

  • 模式如/a\K.(?0)*/匹配“abac”时,Perl和JIT找到“c”,而非“bac”。\K的影响没有被正确传播。并非所有使用\K的情况都会产生错误结果。

  • 使用(*ACCEPT)没有取消其他组捕获,导致ovector包含不正确的信息。例如/(x)|((*ACCEPT))/与“abcd”匹配。

  • 对于类似于在UTF模式下的/(?i)[A-`]/的模式,大小写混合可能会将范围留出类外,在这种情况下,a-j被省略了。

  • 当作为条件使用时,优化为(*FAIL)的断言。例如(?(?!)a|b)

  • 对于\8\9,现在与Perl匹配。它们是反向引用,或者是字面字符“8”和“9”。

  • 报告空子模式名称的错误,例如(?'')

  • 重复非捕获组与匹配空字符串的条件组无法被识别为匹配空字符串。例如/^(?:(?(1)x|)+)+$()/.

  • EBCDIC环境的各种破坏性变化。

  • 启用Unicode支持的PCRE2在类中使用\p\P时未报告错误。

  • 可能匹配空字符串的占有性重复条件组被错误地编译。例如/(?(R))*+/

  • 如果后面跟随单个字符,则序列如[[:punct:]b]会忽略POSIX类。

  • 在UCP模式下,[:punct:]匹配了128-255中不应匹配的字符。

  • 否定类,例如[^[:^ascii:]\d]和非否定类[:^ascii:][:^xdigit:]错误地包括所有大于255的码点。

  • 在模式开头设置任何(?imsxJU)选项不再传递到由PCRE2_INFO_ALLOPTIONS返回的选项中。

  • 在量词符号中间使用\Q\E,例如A+\Q\E+现在被忽略。

  • 调用前的回调后面可以出现一个空的\Q\E序列,但是它会被忽略。

  • 现在可以在回顾断言中的组后使用{0}

  • PCRE2现在匹配perl,将(?(DEFINE)...)视为“定义”组,即使存在名为“DEFINE”的组也是如此。

  • 递归条件测试现在必须引用现有的子模式。例如(?(R2)...)

  • 如果组名以“R”开头,则条件递归测试的使用方式不


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