我有一个相当不错的搜索,虽然有很多类似的问题,但我不相信答案是适用的。
我有一个相当低效的正则表达式搜索一个相当大的字符串。我已经使用精确的正则表达式和字符串在http://regexpal.com中对其进行了测试,并且几乎立即回复了正确的答案。
具有相同输入的C#Regex模块挂起 - 或者至少我已经离开它10分钟来完成regexpal在几分之一秒内可以做的事情。
正则表达式的C#实现是否比http://regexpal.com效率低,还是真的悬挂?正则表达式是搜索两个由未知行数分隔的关键字:
"KEYWORD1(.|\r|\n)+KEYWORD2\t +.+"
字符串长830行,每行约30个字符。
答案 0 :(得分:3)
根据Regular Expression上的文档,.
匹配除\n
之外的任何单个字符。这意味着.
(与Java中的\r
(默认模式),JavaScript等不匹配)与.NET中的\r
匹配。
你的正则表达式有效地允许2个分支用于相同的字符\r
。输入中\r
越多,运行正则表达式所需的时间就越长。在输入失败时,它将根据输入中\r
的数量导致指数复杂性。
请注意,regexpal是一个JavaScript正则表达式测试程序,如上所述,JavaScript中的.
会排除\r
,\n
(以及其他一些行分隔符)。由于它们匹配的内容没有重叠,因此每个角色最多只能有一个分支。
一种解决方案是将(.|\r|\n)+
替换为(?s:.+)
。 s
标志将有效地使.
匹配任何字符,无例外。任何角色只有一个分支,因此没有指数回溯。
+.+
不会导致效率低下,因为它已经处于模式的最后。但是,如果还有其他内容,它可能会导致问题(二次复杂性)。例如,如果最后有$
,那么在失败的情况下,当模式 +.+$
与具有大量空格的后缀匹配时,后跟最后的换行符,则未优化引擎会尝试各种方法将连续的空格分成两部分。
答案 1 :(得分:2)
正如评论中所述,正则表达式的一个常见问题是有一个模式:
Word1.+Word2
因为如果你的文字很大并且有类似的东西:
Word1 ... Word1 ... Word2 ... Word2 ... Word1 .... Word2 ... Word2
您的所有组合与Word1
匹配,以Word2
结尾 - 即使Word1
或Word2
介于它们之间
通常情况下,这不是您正在寻找的内容,并希望在起点和终点之间设置最短的字符集(或者不再显示Word1
)。为此,你的正则表达式最好改为:
Word1.+?Word2
希望这是有道理的。
答案 2 :(得分:-1)
基本上,你的正则表达式是递归的。删除最终.+
可以解决问题。以下是a good article关于避免它的问题。为什么.NET挂起?可能是因为它永远不会中止搜索。也许你使用的JavaScript解析器如果检测到太多步骤或者进入递归搜索太深,就会中止。