有人能告诉我为什么这个C#电子邮件验证的正则表达式(regex)卡住了吗?
有人能告诉我为什么这个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
这个问题的出现的原因是由于正则表达式中存在“灾难性回溯”的情况。简化后的关键部分为(\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
在C#中,使用正则表达式(regex)验证电子邮件是不可靠的,并且可能会导致应用程序卡死。相反,可以使用MailAddress类来验证电子邮件地址的有效性。然而,在Win8 C# / WinRT中,MailAddress类不可用。
以下是验证电子邮件地址的替代方法,并解释了为什么上述的正则表达式会导致卡死:
try { address = new MailAddress(address).Address; //address is valid } catch(FormatException) { //address is invalid }
需要注意的是,在正则表达式中使用了`-`符号时,需要进行转义,即`\-`。
然而,有人指出,只有当`-`不是字符类(`[]`)的第一个或最后一个字符时,才需要进行转义。
所以,以上的正则表达式可能会导致卡死的原因是因为没有对`-`进行转义。
希望这个解决方法能帮助您解决问题。