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

问题描述 投票:0回答:1

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

很多网站讨论了 API 差异,但我没有发现任何列出正则表达式符号中实际差异的网站。虽然我确实知道

[\w-_]
的含义与 PCRE
 中的 
[\w\-_] 相同,但在 PCRE2无效,但我怀疑还存在其他差异。

PCRE2 的正则表达式与 PCRE 的正则表达式有何不同?

regex migration pcre
1个回答
14
投票

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

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

Pcre2 有版本检查模式。您可以在应用程序中检查版本,

/(?(VERSION>=10)yes|no)/
与“yesno”匹配。

可能发生的重大变化:

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

  • 当 Perl 和 JIT 找到“c”时,
  • 诸如

    /a\K.(?0)*/
    之类的模式与“abac”匹配会找到“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 返回的选项。

  • 现在会忽略量词(例如 A+\Q\E+)中间的

    \Q\E

  • 空的

    \Q\E
    序列可能会出现在断言条件之前的标注之后,但会被忽略。

  • 您现在可以在后行断言中的组后面使用

    {0}

  • PCRE2 现在与 perl 相匹配,将

    (?(DEFINE)...)
    视为“定义”组,即使存在名为“DEFINE”的组也是如此。

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

    (?(R2)...)

  • 如果组名以“R”开头,则使用条件递归测试会出现错误。例如

    (?(R)...)

  • 紧跟在 POSIX 字符类后面的连字符与 Perl 不同。允许将其作为文字,但 PCRE2 现在会生成错误。

  • (?=.*X)X$
    这样的模式被错误地优化,就好像它们需要一个初始的“X”和后面的“X”。

  • .*
    开头的断言被错误地优化为需要在主题开头或换行符之后进行匹配。有些情况并不属实,例如
    (?=.*[A-Z])(?=.{8,16})(?!.*[\s])

  • 如果条件子模式中的唯一分支被锚定,则整个子模式将被错误地视为锚定。例如

    /(?(1)^())b/ or /(?(?=^))b/

  • 以子例程调用开头且量词最小值为零的模式将错误地设置“匹配必须以此字符开头”。例如:

    /(?&xxx)*ABC(?<xxx>XYZ)/
    期望“A”是第一个字符。

  • 上游新闻.

  • PHP 7.3 PCRE 迁移说明.

© www.soinside.com 2019 - 2024. All rights reserved.