如何消除此正则表达式的缓慢性?

sYs*_*TeM -1 regex

我有以下正则表达式:

(\d+\s+[-]\s+.*?(?=\s+-)|\d+\s+[-].*)
Run Code Online (Sandbox Code Playgroud)

正则表达式将使用此文本

"Option 01 - Random phrase - Top Menu",
"Option 02 - Another Random Phrase - Su Menu",
"Option 03 - More 01 Phrase - Menu",
"Option 04 - More Phrase -",
"Option 05 - Simple Phrase"
Run Code Online (Sandbox Code Playgroud)

要这样住

01 - Random phrase ",
02 - Another Random Phrase ",
03 - More 01 Phrase ",
04 - More Phrase ",
05 - Simple Phrase ",
Run Code Online (Sandbox Code Playgroud)

此Regex的功能是在开头加上破折号,然后在最后一个破折号前加上数字。例如:

  • dfhdjfhdjf 01-文字 -dkfdçsjf

当最终没有踪迹时,基本上会发生这种情况:

  • dfhdjfhdjf 01-文本文本dkfdçsjf

但是,在regex101.com上调试此正则表达式会导致您需要63到122个步骤。也就是说,此正则表达式非常慢。

在批评这个问题之前,我已经阅读了正则表达式的所有文档,我想让您知道我所指的是特定术语..一个需要解决的问题。毕竟,这不是网站吗?

告诉我,我该如何解决此正则表达式的缓慢性?

Wik*_*żew 5

您不必担心在regex101.com上看到的步骤,因为C#regex库非常可靠。如果您(?s)a.*?b使用很长的字符串测试像regex101 这样的简单正则表达式,它将报告灾难性的回溯,而在C#代码中则可以正常工作。

有一种方法可以改进您的模式,因为它有一些冗余:请参见重复\d+\s+[-]模式。

所有你需要的是

\d+\s+-.*?(?=\s+-|$)
Run Code Online (Sandbox Code Playgroud)

请参阅regex101RegexStorm上的regex演示。

如果.*?(?=\s+-)仅在后面有空格时才匹配-,请使用

\d+\s+-(?:\s.*?(?=\s+-)|.+)
Run Code Online (Sandbox Code Playgroud)

参见另一个演示1(更少的步骤:))/ 演示2

如果您想进一步优化它,则可能需要研究导致问题的展开原理

\d+\s+-(?:\s+\S*(?:\s(?!\s*-)\S*)*|.+)
Run Code Online (Sandbox Code Playgroud)

请参阅此正则表达式演示(最少的步数)。

在这里,\S*(?:\s(?!\s*-)\S*)*是的等效项(几乎).*?(?=\s+-|$),但是效率更高,因为直至空白的块都以“批”进行匹配,仅当遇到空白时才进行连字符检查。

细节

  • \d+ -1个以上的数字
  • \s+ -1+空格
  • - -连字符
  • .*?(?=\s+-|$)-直到第一次出现1+个空格和/ -或直到字符串末尾的任何0+个字符,尽可能少。
  • (?:\s.*?(?=\s+-)|.+) -非捕获组:
    • \s.*?(?=\s+-) -空格,最多0个字符,最多1个空格, -
    • | - 要么
    • .+ -字符串的其余部分。
  • \S*(?:\s(?!\s*-)\S*)*
    • \S* -0+个非空白字符
    • (?:\s(?!\s*-)\S*)* -重复0次或以上
      • \s -空格
      • (?!\s*-) -后面没有0+空格, -
      • \S* -0+个非空白字符