提高 PCRE 正则表达式模式的性能

Improving the performance of an PCRE Regex Pattern

我这里有下面的正则表达式,它是为支持 PRCE/PRCE2 格式而编写的。但是,这会引发以下错误 “评估时间过长。请检查您的正则表达式。”我们是否可以通过简化此正则表达式来提高性能?

此外,正则表达式也会抛出 “灾难性回溯” 错误。

(\border\D*\W*)\d+(*SKIP)(*F)|(\border\D*number\W*)\d+(*SKIP)(*F)|(?<!x)(?=(?:[._ –-]*\d){9})(?!9|66\D*6|00\D*0|(?:\d\D*){3}0\D*0|(?:\d\D*){5}0(?:\D*0){3})\d(?:[._ –-]*\d){4}

Regex Demo here

上面的正则表达式中有一组规则。请找到正则表达式的要求。

  1. 前 5 个号码只能被屏蔽在 9 位号码中。
  2. 如果 'x' 或 'X' 位于 9 位数字之前,则不应屏蔽任何数字。
  3. 如果“订单”或“订单号”字符串在 9 位数字之前,则不应匹配。
  4. 您可以在此 link 中找到相同的用例列表以及规则。 Usecases with requirements

Regex101 为我提供了预期的准确输出,但它存在性能问题。需要简化一下。

您可以试试这个重构的正则表达式:

\b(?>x|order(?>[\W_]*number)?[\W_]*)\d+(*SKIP)(*F)|(?=(?>[._ –-]*\d){9})(?>(?>9|6{3}|0{3}|(?>\d\D*){3}00|(?>\d\D*){5}0{4})(*SKIP)(*F)|\d(?>\D*\d){4})

RegEx Demo

与您现有的演示 link 相比,它在演示 link 中花费了几乎一半的步骤。

其他方法:扩展模式!

~(*UTF)
    x (?<! \w x ) [\d._ –-]* (*SKIP) (*F)
  |
    order (?<! \w order ) [\W_]* (?:number)? [\W_]* [\d._ –-]* (*SKIP) (*F)
  |
    (?<res>
      [1-578]  (?: [._ –-]{0,3}+ \d ){2}  (?: 0{2}  [\d._ –-]* (*SKIP) (*F) )?
      (?: [._ –-]{0,3}+ \d ){2}
    )
    (?: 0{4} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){4}
  |
    (?<res>
      0  (?: 0{2} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){2}
      (?: 0{2} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){2}
    )
    (?: 0{4} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){4}
  |
    (?<res>
      6  (?: 6{2} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){2}
      (?: 0{2} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){2}
    )
    (?: 0{4} [\d._ –-]* (*SKIP) (*F) )?  (?: [._ –-]{0,3}+ \d ){4}
  |
    9 [\d._ –-]* (*SKIP) (*F)
~iJx

花样确实比较长,但是2 times faster and with 8 times fewer steps.

注意我用了一个capture group来提取前5位,剩下的4位也被消耗了,但是如果你愿意,你也可以去掉这个capture group,把剩下的4位放在lookahead中(more steps but more efficient).

我从 (*UTF) 开始模式,因为它包含一个超出 ascii 范围的破折号。