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');
}
所以我写了这个正则表达式来验证电子邮件地址:
(?=^([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');
}