正则表达式对大型文档极其缓慢

时间:2012-10-10 05:31:48

标签: c# regex

运行以下代码时,CPU负载会上升,并且在较大的文档上需要时间:

string pattern = @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
Regex regex = new Regex(
      pattern,
      RegexOptions.None | RegexOptions.Multiline | RegexOptions.IgnoreCase);

MatchCollection matches = regex.Matches(input); // Here is where it takes time
MessageBox.Show(matches.Count.ToString());

foreach (Match match in matches)
{
    ...
}

知道如何加快速度吗?

3 个答案:

答案 0 :(得分:2)

RegexOptions.None | RegexOptions.Multiline | RegexOptions.IgnoreCase更改为RegexOptions.Compiled会产生相同的结果(因为您的模式不包含任何文字字母或^ / $)。

在我的机器上,这会将您链接的样本文档所花费的时间从46秒减少到21秒(这对我来说似乎仍然很慢,但对您来说可能已经足够了)。

编辑:所以我对此进行了一些调查并发现了真正的问题。

问题在于你的正则表达式的前半部分:\w+([-.]\w+)*\.\w+([-.]\w+)*@。这在匹配实际包含@符号的输入部分时效果很好,但对于仅匹配\w+([-.]\w+)*\.\w+([-.]\w+)*不是后跟@的部分,正则表达式引擎浪费了大量时间回溯并从序列中的每个位置重试(并再次失败,因为仍然没有@!)

您可以使用\b强制匹配从字边界开始来解决此问题:

 string pattern = @"\b\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";

在您的示例文档中,这会在1秒内生成相同的10个结果。

答案 1 :(得分:0)

尝试将regex用于streams,使用 mono-project regex,这篇文章对.Net

有用

并尝试提高您的正则表达能力。

答案 2 :(得分:0)

要回答如何更改它,您需要告诉我们它应该匹配的内容。

问题可能在最后一部分@\w+([-.]\w+)*\.\w+([-.]\w+)*。在字符串“bla@a.b.c.d.e-f.g.h”上,它必须尝试许多可能性,直到找到匹配为止。

可能有点Catastrophic Backtracking

因此,您需要以更好,更“独特”的方式定义模式。你真的需要“Dash / dot - dot - dash / dot”吗?