字符串正则表达式用户名或电子邮件挂起

use*_*220 2 javascript regex jquery

验证用户名输入字段时出现问题.

正则表达式:

var mailformat = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/;
var letterNumber = /^[0-9a-zA-Z]*$/;
Run Code Online (Sandbox Code Playgroud)

支票 :

if (!letterNumber.test($('#login_username').val()) 
      && !mailformat.test($('#login_username').val())){
 ...
}
Run Code Online (Sandbox Code Playgroud)

当我想用此条目验证时,浏览器(chrome和ie)会挂起:

012345678901234567890123456789@
Run Code Online (Sandbox Code Playgroud)

任何人都知道为什么?

我在一个表达式中尝试使用正则表达式,但得到了相同的结果.(正则表达式是可以的,因为他们分开工作)

Rob*_*bin 5

你偶然发现了灾难性的回溯!

要修复它,您可以使用:

^\w+([.-]\w+)*@\w+([.-]\w+)*(\.\w{2,4})+$
Run Code Online (Sandbox Code Playgroud)

在声明匹配失败之前,正则表达式引擎必须检查应用正则表达式的所有可能方法.

使用时\w+([.-]?\w+)*,每个数字可以匹配\w+或通过匹配([.-]?\w+)*,并且在失败时([.-]?\w+)*可以表现相同(\w+)*.这创造了许多州的回归.

使得[.-]强制消除这种不确定性.


(灾难性)回溯

正则表达式引擎的工作方式是它在正则表达式中移动,试图将它的每个部分与字符串相匹配.每次它有一个选择,它会保存状态,以便它可以回溯到它,如果这是错误的路径.

为了说明,看看有多.*b匹配abc.

  • .*量词是贪婪的,因此会尽可能地匹配:它首先没有匹配,然后添加a,然后添加b,然后添加c.每次引擎记住它就选择添加另一个角色.然后引擎尝试匹配b,但我们在字符串的末尾,所以失败.

  • 没什么大不了的,我们回到最后的选择:现在.*只有匹配ab.最后b仍然与字符串的结尾不匹配c.

  • 我们更进一步:.*匹配a,b终于可以匹配了.总体匹配发现:ab

在知道正则表达式与输入不匹配之前,引擎必须尝试所有这些替代方案.如果允许字符与正则表达式的多个部分匹配,则该数字会增加.

在你的情况下,它随着字符串的长度呈指数增长,直到它需要永远返回任何东西:这是灾难性的回溯.

Friedl关于这个主题的精彩插图:http://www.foo.be/docs/tpj/issues/vol1_2/tpj0102-0006.html