使用正则表达式评估电子邮件地址时出现性能问题

6

我正在使用以下正则表达式来验证电子邮件地址。

/^\w+([\.-]?\w+)*@\w+([\.-]?w+)*(\.\w{2,3})+$/

Javascript代码:

var email = 'myname@company.com';

var pattern = /^\w+([\.-]?\w+)*@\w+([\.-]?w+)*(\.\w{2,3})+$/;

if(pattern.test(email)){
    return true;
}

当我提供以下无效电子邮件时,正则表达式的评估速度很快:
aseflj#$kajsdfklasjdfklasjdfklasdfjklasdjfaklsdfjaklsdjfaklsfaksdjfkasdasdklfjaskldfjjdkfaklsdfjlak@company.com

我在名称中间添加了#$

然而,当我尝试评估此电子邮件时,它会花费太长时间,并且浏览器会挂起。

asefljkajsdfklasjdfklasjdfklasdfjklasdjfaklsdfjaklsdjfaklsfaksdjfkasdasdklfjaskldfjjdkfaklsdfjlak@company.com1

我相信正则表达式是正确的,但不确定为什么在评估第二个示例时需要这么长的时间。如果我提供长度较短的电子邮件,它会快速评估。请参见以下示例:

(我在末尾添加了com1

dfjjdkfaklsdfjlak@company.com1

请帮助我解决性能问题。


最奇怪的部分是,使用动态规划,可以在O(n)时间内评估每个(常规)正则表达式。因此,评估应该非常快速。 - Willem Van Onsem
2
看起来正则表达式不太好。如果你在Regex101中尝试使用你的模式和测试数据,你会发现它在两秒后停止并告诉你你的正则表达式有问题,然后指向这个灾难性回溯。我猜测时间是按字符呈指数级增长的,因为模式的设计方式。 - James Hay
1
移除 ? 似乎也解决了灾难性回溯问题(即使用 /^\w+([\.-]?\w+)*@\w+([\.-]?w+)*(\.\w{2,3})+$/ 替代)。我不确定这对您是否足够好,或者它是否无法通过任何测试用例。但它以一种微不足道的方式解决了主要的性能问题。@James Hay 的方法可能更好。 - GregL
1
@GregL 在这种情况下,你的步骤似乎更短,只有18步,而我的则是26步。两者都比原始步骤(115924步)要好! - James Hay
1
@GregLпјҡжҲ‘дјҡеңЁ[\.-]?дёӯеҺ»жҺү?гҖӮиҝҷжҳҜдёҖз§ҚеҸҜиғҪеҜјиҮҙзҒҫйҡҫжҖ§еӣһжәҜзҡ„жҪңеңЁжқҘжәҗгҖӮ - nhahtdh
显示剩余2条评论
1个回答

5
你的正则表达式遇到了灾难性回溯。由于[\.-]?([\.-]?\w+)*中是可选的,它使得该组退化为(\w+)*,这是灾难性回溯的典型案例。
去掉?即可解决此问题。
我还删除了字符类内部冗余的.转义,并略微修改了正则表达式。
^\w+([.-]\w+)*@\w+([.-]\w+)*\.\w{2,3}$

请注意,许多新的通用顶级域名具有超过3个字符。即使扩展之前的某些通用顶级域名也具有超过3个字符,例如.info
目前,该正则表达式也不支持国际化域名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接