有人能告诉我为什么这个C#电子邮件验证的正则表达式(regex)卡住了吗?

8 浏览
0 Comments

有人能告诉我为什么这个C#电子邮件验证的正则表达式(regex)卡住了吗?

我从Email regular expression中得到了一个好的电子邮件验证正则表达式。

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); // 在这里卡住了!?!
    return;
}

它在大多数情况下可以工作,但是上面的代码会卡住,占用100%的CPU... 我在一个W8 Metro应用程序和一个标准的.Net 4.5应用程序中进行了测试。

有人能告诉我为什么会发生这种情况,是否有一个不会卡住的好的电子邮件验证正则表达式,或者是否有一种修复这个问题的方法?

非常感谢,

Jon

0
0 Comments

问题出现的原因是原来的正则表达式中的[-.\w]导致程序卡住,解决方法是使用新的正则表达式。此外,还可以尝试使用.NET 4.5中的EmailAttribute进行邮箱验证。另外,正则表达式并不适合用于邮箱验证,因为实际的邮箱验证正则表达式会比这个要复杂得多。可以考虑使用MailAddress类进行邮箱验证,也可以根据不同国家的邮箱规则使用不同的正则表达式进行验证。

0
0 Comments

这个问题的出现的原因是由于正则表达式中存在“灾难性回溯”的情况。简化后的关键部分为(\w*[0-9a-zA-Z])*@。这个正则表达式中存在可选部分\w*,它可以匹配与后面的部分[0-9a-zA-Z]相同的字符,因此两者合并实际上等同于\w+。还存在嵌套的量词(\w+)*,这意味着对于给定的s = "cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc",在找不到后面的@时,这部分正则表达式需要检查s的所有可能排列(共有2**(len(s)-1)个)。

由于没有任何正则表达式可以完全验证电子邮件地址(规范中存在太多的特殊情况),通常最好的做法是:

- 进行最简化的正则表达式检查(^.*@.*$

- 使用解析器进行验证(如.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);

你好,谢谢你的详细回答 🙂 我将采用“进行最简化的正则表达式检查(^.*@.*$)”的验证方法 - 因为我们只是想帮助用户避免输入错误,比如输入“..”。如果他们输入了错误的地址,也不是世界末日,因为我们还有其他的电子邮件恢复机制。谢谢,Jon

0
0 Comments

在C#中,使用正则表达式(regex)验证电子邮件是不可靠的,并且可能会导致应用程序卡死。相反,可以使用MailAddress类来验证电子邮件地址的有效性。然而,在Win8 C# / WinRT中,MailAddress类不可用。

以下是验证电子邮件地址的替代方法,并解释了为什么上述的正则表达式会导致卡死:

try 
{
    address = new MailAddress(address).Address;
   //address is valid
} 
catch(FormatException)
{
    //address is invalid
}

需要注意的是,在正则表达式中使用了`-`符号时,需要进行转义,即`\-`。

然而,有人指出,只有当`-`不是字符类(`[]`)的第一个或最后一个字符时,才需要进行转义。

所以,以上的正则表达式可能会导致卡死的原因是因为没有对`-`进行转义。

希望这个解决方法能帮助您解决问题。

0