【问题标题】:Regex takes a long time to complete正则表达式需要很长时间才能完成
【发布时间】:2016-04-26 11:58:05
【问题描述】:

我想匹配一个结构如下的行:

  • 行首
  • 多个'-'
  • 可能是空白(可能更多)
  • 至少一个字符
  • 可能有更多字符和空格
  • 可能是空白(可能更多)
  • 多个'-'
  • 行尾

所以我这样写了正则表达式:

new Regex(@"^\-{2,}\s*(\w+(\w+|\s)*)\s*\-{2,}$");

当我尝试匹配以下行时,这需要很长时间才能完成(没有等待它完成):

-------- Variable used for recipe visualization only - Not loaded into PLC --------

我认为其中有大量匹配项,Regex 很难枚举所有这些匹配项,但我不确定。

环境信息:Windows 7,framework 3.5

谢谢

编辑:感谢您的帮助,我想出了一个有效的正则表达式:

^-{2,}\s*(?!\-)(\w(?:\w|\s|\-)+)(?<!\-)\s*-{2,}$

所以解释:

  • 行首
  • 至少两个'-'
  • 可能是空白(可能更多)
  • 没有更多的'-'
  • 至少一个字符
  • 可能有更多字符、空格或“-”
  • 没有更多的'-'
  • 可能是空白(可能更多)
  • 至少两个'-'
  • 行尾

如果你发现有问题请告诉我

【问题讨论】:

  • 这不匹配,因为“仅 - 不”中的内部破折号。
  • 您的问题是您不允许捕获中间的` - `
  • 我刚刚在myregextester.com/index.php 上试过这个,它在 0.018301 秒内运行。但是在 C# 中运行确实需要很长时间,但删除内部破折号确实会加快速度。
  • @juharr 和 Jonesopolis 感谢您的回答。但是为什么它不能只返回false而不是运行很长时间呢?
  • 我希望这部分负责:(\w+(\w+|\s)*)。基本上,只要空格序列保持不变,您就可以对单词和空格序列进行任何分区。由于整个表达式不匹配,回溯将依次访问所有允许的分区。尝试将其替换为(\w+(\s+\w+)*)

标签: c# .net regex


【解决方案1】:

将嵌套分组展开为

^-{2,}\s*(\w+(?:\s+\w+)*)\s*-{2,}$
             ^^^^^^^^^^^ 

否则,您的模式将容易出现catastrophic backtracking

regex demo

或者,使用原子组禁用任何回溯到交替组:

^-{2,}\s*((?>\w+(?:\w+|\s)*))\s*-{2,}$
          ^^^              ^ 

this regex demo

一般来说,避免在较长的模式中使用嵌套量词(如(\w+|\s)*)。

【讨论】:

  • 编辑了我的答案以包含适用于这种情况的正则表达式。你能看一下并告诉我它是否有问题吗?谢谢
  • 正则表达式不是最优的。 (?!-) 完全是多余的,因为下一个子模式是 \w,因此前瞻检查结果始终为 true。我将重写为^-{2,}\s*(\w+(?:[\s-]+\w+)*)\s*-{2,}$(?&lt;!-) 不是必需的,因为最后一个可选空格和连字符之前唯一可能的字符可以是单词字符。请注意,- 不必在字符类之外转义.
猜你喜欢
  • 2011-03-25
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 2016-07-30
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多