c# - 为什么正则表达式在 C# 中挂起

标签 c# regex

我进行了相当不错的搜索,虽然有很多类似的问题,但我认为答案不适用。

我有一个相当低效的正则表达式来搜索相当大的字符串。我在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/

相关文章:

c# - 如何使用 TweetSharp 获取我的直接消息?

c# - 在 C# 中编码(marshal) C 数组

c# - 通过分隔符拆分字符串,将字符串列表转换为对象列表

regex - 是否可以使用raku regex进行 bool 断言?

arrays - Ruby 匹配数组中的字符串

Java:匹配具有未知字符的字符串的算法

c# - 使用 .NET Core 2.2 从 Azure 存储获取所有 Blob

c# - 是否有内置方法将 HRESULT 表示为 winerror.h 常量(例如 E_FAIL)?

php - 从字符串中删除特殊字符

regex - 如何从两个文件中读取内容并合并到 bash shell 中的第三个文件