我进行了相当不错的搜索,虽然有很多类似的问题,但我认为答案不适用。
我有一个相当低效的正则表达式来搜索相当大的字符串。我在http://regexpal.com测试过使用准确的正则表达式和字符串,它几乎立即返回正确答案。
具有相同输入的 C# Regex 模块挂起 - 或者至少我已经让它 10 分钟来完成 regexpal 可以在几分之一秒内完成的事情。
Regex 的 C# 实现是否比 http://regexpal.com 效率低得无可救药? ,还是真的挂了?正则表达式是搜索由未知行数分隔的两个关键字:
"KEYWORD1(.|\r|\n)+KEYWORD2\t +.+"
字符串长830行,每行约30个字符。
最佳答案
根据 Regular Expression 上的文档, .
匹配除 \n
之外的任何单个字符。这意味着 .
(与 Java(默认模式)、JavaScript 等中的 \r
不匹配)与 . NET.
您的正则表达式有效地允许同一字符 \r
有 2 个分支。输入中的 \r
越多,运行正则表达式所需的时间就越长。对于失败的输入,它会根据输入中 \r
的数量导致指数复杂度。
注意 regexpal 是 JavaScript 正则表达式测试器,并且如前所述,JavaScript 中的 .
排除了 \r
、\n
(以及一些其他行分隔符)。由于它们匹配的内容没有重叠,因此每个字符最多可以跟随 1 个分支。
一种解决方案是用 (?s:.+)
替换 (.|\r|\n)+
。 s
标志将有效地使 .
无一异常(exception)地匹配任何字符。任何字符只有一个分支,因此没有指数回溯。
+.+
在这种情况下不会造成太多效率低下,因为它已经在模式的末尾。但是,如果后面还有其他东西,它可能会导致问题(二次复杂性)。例如,如果末尾有 $
,那么在失败的情况下,当模式 +.+$
与包含大量空格的后缀匹配时,后跟最后一个换行符,然后未优化的引擎将尝试所有方法将连续的空格分成两部分。
关于c# - 为什么正则表达式在 C# 中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27254724/