繁体   English   中英

随机 RegexMatchTimeoutException 异常

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM