任何人都可以告诉我为什么这个C#电子邮件验证正则表达式(正则表达式)挂起?

Jon*_*Rea 5 c# regex

我有一个很好的电子邮件vaidation正则表达式: 电子邮件正则表达式

    public static void Main(string[] args)
    {
        string value = @"cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc";
        var regex = new Regex(
            @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$",
            RegexOptions.Compiled);
        var x = regex.Match(value); // Hangs here !?!
        return;
    }
Run Code Online (Sandbox Code Playgroud)

它适用于大多数情况,但上面的代码挂起,燃烧100%CPU ...我已经在W8 metro应用程序中测试过.以及标准的.Net 4.5应用程序.

任何人都可以告诉我为什么会发生这种情况,如果有一个好的电子邮件验证REGEX没有挂起,或者有没有办法解决这个问题?

非常感谢,乔恩

Tim*_*ker 14

解释为什么它挂起:灾难性的回溯.

让我们简化正则表达式的关键部分:

(\w*[0-9a-zA-Z])*@
Run Code Online (Sandbox Code Playgroud)

你有

  • 一个可选的部分\w*,可以匹配与下一部分相同的字符[0-9a-zA-Z],所以这两个组合翻译,实质上是\w+
  • 嵌套量词: (\w+)*

这意味着,给定s = "cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc",正则表达式的这一部分需要检查所有可能的排列s(在哪个数字处2**(len(s)-1)),然后在@未找到以下内容时确定不匹配.

由于您无法使用任何正则表达式验证电子邮件地址(规范中存在太多极端情况),因此通常最好

  • 做一个最小的正则表达式检查(^.*@.*$)
  • 使用解析器检查有效性(如@ Fake.It.Til.U.Make.It建议)
  • 尝试向它发送电子邮件 - 即使看似有效的地址也可能是假的,所以无论如何你都必须这样做.

为了完整起见,您可以原子组的帮助下避免回溯问题:

var regex = new Regex(
    @"^([0-9a-zA-Z](?>[-.\w]*[0-9a-zA-Z])*@(?>[0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$",
    RegexOptions.Compiled);
Run Code Online (Sandbox Code Playgroud)