[英]Random RegexMatchTimeoutException exceptions
在解析短(少于 100 个字符)字符串时,我有时会遇到RegexMatchTimeoutException
。 解析本身位于 function 中的list.Select(..)
中,该集合包含大约 30 个元素。
我怀疑这可能是由于次优正则表达式 - 这是 C# 中的定义:
internal override Regex Regex => new(
@$"((.|\s)*\S(.|\s)*)(\[{this.Type}\])", // Type = "input"
RegexOptions.Multiline | RegexOptions.Compiled,
TimeSpan.FromMilliseconds(Constants.RegexTimeout)); // RegexTimeout = 100
它应该捕获以下字符串中的Sample text
:
Sample text
[input]
完整异常消息:
System.Text.RegularExpressions.RegexMatchTimeoutException: 'The Regex engine has timed out while trying to match a pattern to an input string. This can occur for many reasons, including very large inputs or excessive backtracking caused by nested quantifiers, back-references and other factors.'
发生异常的行:
var label = this.Regex.Match(sectionContent).Groups[1].Value.Trim();
异常很难重现——使用相同的输入,它可能在第一次运行或第 100 次运行时发生。 但是运行正则表达式的行集合越大,它发生的可能性就越大。
您的((.|\s)*\S(.|\s)*)(\[input\])
正则表达式匹配
((.|\s)*\S(.|\s)*)
- 第 1 组:
(.|\s)*
- 除换行符 ( .
) 或 ( |
) 以外的任何字符出现零次或多次,任何空白字符 ( \s
)\S
- 非空白字符(.|\s)*
- 除换行符 ( .
) 或 ( |
) 以外的任何字符出现零次或多次,任何空白字符 ( \s
)(\[input\])
- 第 2 组: [input]
。 您不得不注意到第 1 组模式中的每一个都可以匹配相同的字符。 \S
是这里唯一的“锚定”模式,它需要一个非空白字符,并且由于\S
之前和之后的模式都用于匹配任何文本,因此最有效的逻辑是:匹配任意数量的空白,然后非空白字符,然后是任意数量的字符(尽可能少但尽可能多)直到[input]
。
这是修复:
internal override Regex Regex => new(
@$"(?s)(\s*\S.*?)(\[{Regex.Escape(this.Type)}])", // Type = "input"
RegexOptions.Compiled,
TimeSpan.FromMilliseconds(Constants.RegexTimeout)); // RegexTimeout = 100`
请注意,可以转义this.Type
以防万一其中有任何特殊字符。 (?s)
是RegexOptions.Singleline
选项的内联修饰符版本(可互换使用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.