JS 正则表达式冻结了我的浏览器

JS regex freezes my browser(s)

所以我写了这个正则表达式来验证电子邮件地址:

(?=^([A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$)

我想在 js 控制台中测试它:

var patt = new RegExp("(?=^([A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$)")

patt.test("jake@domain.domain.domain.domain.domai.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domai")

这冻结了我的标签。较短的地址似乎工作正常。

在 C# 和在线正则表达式工具(例如 regex101.com)中测试没有任何问题。 这是怎么回事? JavaScript 正则表达式引擎有问题,还是只是我的正则表达式?

(我知道这可能不是一个完美的电子邮件验证,但这个问题是关于为什么它不起作用)

使用 RegExp 文字而不是 RegExp 构造函数:

/(?=^(?:[A-Za-z0-9_\xC0-\xFF!#$%&'*+\/=?^`{|}~\-]\.?){0,63}[A-Za-z0-9_\xC0-\xFF!#$%&'*+\/=?^`{|}~\-]@[A-Za-z0-9\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?(?:\.[A-Za-z\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?)*$)(?=^.{3,254}$)/

我冒昧地删除了字符 class 中过多的转义(在 JavaScript 中,只有 ]\ 需要转义,^如果它不在一个字符的开头不需要转义 class,- 如果它在一个字符的结尾不需要转义 class) 并使所有捕获组非捕获(因为您不关心捕获的内容)。

当你使用正则表达式构造函数时,你需要提供一个字符串。您需要转义 \ 才能在字符串文字中指定它;否则,它将被视为字符串中的转义序列,并且 \ 将不会到达 RegExp 构造函数。

您可以将字符串复制并粘贴到浏览器控制台的 RegExp 构造函数中。在 Firefox 34.0 上:

"(?=^([A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$)"
>>> "(?=^([A-Za-zÀ-ÿ0-9!#$%&'*+-/=?^\_`{|}~].?){0,63}[A-Za-zÀ-ÿ0-9!#$%&'*+-/=?^\_`{|}~]@[A-Za-zÀ-ÿ0-9]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?(.[A-Za-zÀ-ÿ]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?)*$)(?=^.{3,254}$)"

虽然对于大部分的部分没有问题,但是+-/在字符class中形成了一个字符范围,其中包括,.(字符不打算出现在 class 中)。你得到的是全点 . 而不是文字点,这就是这里发生灾难性回溯的原因:

(.[A-Za-zÀ-ÿ]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?)*

基于上面的 RegExp 文字,使用 RegExp 构造函数的等效代码是:

new RegExp("(?=^(?:[A-Za-z0-9_\xC0-\xFF!#$%&'*+/=?^`{|}~\\-]\.?){0,63}[A-Za-z0-9_\xC0-\xFF!#$%&'*+/=?^`{|}~\\-]@[A-Za-z0-9\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?(?:\.[A-Za-z\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?)*$)(?=^.{3,254}$)")

请注意,与 RegExp 文字相比,所有 \ 都翻了一番。

不过,没有理由使用 RegExp 构造函数。仅当您需要根据某些输入生成正则表达式时才应使用它。固定正则表达式应指定为 RegExp 文字。

You can use this one. it will support after [dot] 2 ,3 character as per your domain

var email_filter  = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
if (email_filter.test('yourEmail@gmail.com')) {
  alert('Email is valid');
}