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