如果您能发布导致问题的电子邮件(以某种方式匿名化),那将为我们提供更多信息,但我认为问题就在这里这个小家伙:
。
([-.]\\w+)*\\.\\w+([-.]\\w+)*
为了理解问题,让我们将其分成几组:
([-.]\\w+)*
\\.\\w+
([-.]\\w+)*
匹配
\\.\\w+
的字符串是匹配
[-.]\\w+
的一个子集。所以,如果您的输入的一部分看起来像
foo.bar.baz.blah.yadda.com
,则您的正则表达式引擎无法知道哪个组应该匹配它。这有道理吗?因此,第一个
([-.]\\w+)*
可以匹配
.bar.baz.blah
,然后
\\.\\w+
可以匹配
.yadda
,最后一个
([-.]\\w+)*
可以匹配
.com
...
...或者第一个条款可以匹配.bar.baz
,第二个可以匹配.blah
,最后一个可以匹配.yadda.com
。由于引擎不知道哪个正确,它将继续尝试不同的组合。它应该最终停止,但这可能仍需要很长时间。这被称为“灾难性回溯”。
这个问题还因为您使用了捕获组而不是非捕获组而更加严重;即([-+.]\\w+)
而不是(?:[-+.]\\w+)
。这会导致引擎尝试分离和保存括号内的任何匹配项以备以后参考。但正如上面所解释的那样,每个子字符串属于哪个组是模糊的。
您可以考虑用类似以下内容替换@后面的所有内容:
\\w[-\\w]*\\.[-.\\w]+
这需要进行一些完善以使其更加具体,但总体的概念已经清楚了。希望我解释得足够好;分组和回溯有点难描述。
编辑:
回顾您的模式,这里还存在一个更深层次的问题,仍然与我提到的回溯/歧义问题相关。子句 \\w+([-.]\\w+)*
本身就是有歧义的。将其分成几个部分,我们有:
\\w+
([-.]\\w+)*
假设您有一个字符串,如
foobar
。
\\w+
的结束位置在哪里,
([-.]\\w+)*
开始呢?
([-.]\\w+)
重复多少次?以下任何一种都可以作为匹配项:
f(oobar)
foo(bar)
f(o)(oba)(r)
f(o)(o)(b)(a)(r)
foobar
etc...
正则表达式引擎不知道哪个更重要,因此它会尝试所有可能性。这是我上面指出的同样的问题,但它意味着您在模式中有多个位置存在该问题。
更糟糕的是,由于
\\w
后面跟着
+
,
([-.]\\w+)*
也是含糊不清的。在
blah
中有多少组?我数了16种可能的组合:
(blah)
,
(b)(lah)
,
(bl)(ah)
...
即使对于相对较小的输入,可能的不同组合数量也会非常庞大,因此您的引擎将超负荷运行。如果我是您,我肯定会简化它。
@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
- R. Martinho Fernandes