JS正则表达式冻结了我的浏览器 [英] JS regex freezes my browser(s)

查看:80
本文介绍了JS正则表达式冻结了我的浏览器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So I wrote this Regex for validating e-mail addresses:

(?=^([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控制台中测试它:

And I wanted to test it in js console:

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")

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

And that freezes my tab. Shorter addresses seem to be working fine.

使用C#和在线正则表达式工具进行测试(例如 regex101.com )没有任何问题。
发生了什么事? JavaScript Regex引擎是否有问题,或者它只是我的正则表达式?

Tested in C# and online regex tools (e.g. regex101.com) without any problems. What's going on? Is the JavaScript Regex engine faulty, or is it just my Regex?

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

(I am aware that this might not be a perfect email validation, but this question is about why doesn't it work)

推荐答案

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

Use RegExp literal instead of RegExp constructor:

/(?=^(?:[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}$)/

我冒昧地删除了字符类中的过多转义(在JavaScript中,只有] \ 需要转义, ^ 如果需要转义,则不需要转义它不是在角色类的开头, - 如果它位于字符类的末尾则不需要转义)并使所有捕获组都不捕获(因为你不关心捕获的内容) 。

I have taken the liberty of removing excessive escaping inside the character class (in JavaScript, only ], \ needs escaping, ^ don't need escaping if it is not at the start of a character class, - don't need escaping if it is at the end of a character class) and make all the capturing groups non-capturing (since you don't care about the captured content).

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

When you use RegExp constructor, you need to supply a string. You need to escape \ in order to specify it in a string literal; otherwise, it will be treated as an escape sequence in string and the \ will not reach the RegExp constructor.

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

You can copy and paste your string inside the RegExp constructor in the console of your browser. On 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}$)"

虽然对于大多数零件来说不是问题, + - / 在角色类中形成一个字符范围,其中包括(不打算出现在班级中的字符)。并且你得到了点全部而不是文字点,这是灾难性回溯的原因:

While it is not a problem for most of the parts, +-/ forms a character range in the character class, which includes , and . (characters not intended to be in the class). And you get the dot-all . instead of literal dot, which is the reason for catastrophic backtracking here:

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

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

Basing on the RegExp literal above, the equivalent code using RegExp constructor is:

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文字相比,所有 \ 都加倍。

Note that all \ are doubled up compared to the RegExp literal.

没有理由使用RegExp但是构造函数。它只应在需要根据某些输入生成正则表达式时使用。固定正则表达式应指定为RegExp文字。

There is no reason to use the RegExp constructor, though. It should only be used when you need to generate regex based on some input. Fixed regex should be specified as RegExp literal.

这篇关于JS正则表达式冻结了我的浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆