为什么这个JavaScript正则表达式很慢? var email='[John Smith]'; 变量re1=/.*/; 变量re2=/.\[+(.*)+\]./; var地址=email.replace(re1,“$1”); 变量名称=email.replace(re2,“$1”);

为什么这个JavaScript正则表达式很慢? var email='[John Smith]'; 变量re1=/.*/; 变量re2=/.\[+(.*)+\]./; var地址=email.replace(re1,“$1”); 变量名称=email.replace(re2,“$1”);,javascript,regex,Javascript,Regex,我发现第二个正则表达式(取名字)运行得非常慢。但是第一个很好。这是为什么?有没有更好的方法来获取我需要的字符串?不确定您的性能问题(如果有),但您可以使用单个正则表达式来提取这两个值: var email = '[John Smith] <johnsmith@gmail.com>'; var re1 = /.*<+(.*)+>.*/; var re2 = /.*\[+(.*)+\].*/; var address = email.replace(re1, "$1");

我发现第二个正则表达式(取名字)运行得非常慢。但是第一个很好。这是为什么?有没有更好的方法来获取我需要的字符串?

不确定您的性能问题(如果有),但您可以使用单个正则表达式来提取这两个值:

var email = '[John Smith] <johnsmith@gmail.com>';

var re1 = /.*<+(.*)+>.*/;
var re2 = /.*\[+(.*)+\].*/;

var address = email.replace(re1, "$1");
var name = email.replace(re2, "$1");
var str='[John Smith]',
re=/\[(.+)\]/,,
name=str.match(re)[1],
email=str.match(re)[2];
console.log(名称、电子邮件);//=>“约翰·史密斯johnsmith@gmail.com"

正则表达式速度慢的原因是它们编写得非常糟糕

现在,让我们继续说为什么他们是坏的


您的第一个表达式有一堆不必要的标记。例如引线和尾随
*
-它们没有区别。其次,您对
进行了量化,这是由于使用了许多贪婪的
*
以及字符串的形式为
“[…]”

每次使用
*
而不使用
,RegExp引擎都会选择整个字符串的其余部分,然后在RegExp的以下部分失败时一次向后移动一个字符,测试下一部分

正如您重复的那样,
*
s,这意味着您告诉它从RegExp引擎必须回溯的字符串末尾开始,对每个字符执行指数级的更多测试。贪婪的
+
符号再次重复
*
正在做的事情,这让情况变得更糟

仅仅添加
s并不是最好的修复方法,因为您对字符串了解得更多,而且您不需要在其中寻找太多内容。因此,为了让它不那么“坏”,做一些事情,比如只匹配你感兴趣的部分

var str = '[John Smith] <johnsmith@gmail.com>',
    re = /\[(.+)\] <(.+)>/,
    name = str.match( re )[1],
    email = str.match( re )[2];

console.log( name, email ); //=> "John Smith johnsmith@gmail.com"
var re1=/\]*)>/,
re2=/\[([^\]]*)\]/;
var地址=email.match(re1)[1],
uname=email.match(re2)[1];//避免“window.name”冲突

你是如何衡量的?另外,由于在这种特殊情况下,这些不会改变结果,我认为regexOh wow中的
+
符号的意义对我来说并不那么意外,因为
位于字符串的末尾,第一个表达式必须比第二个表达式进行更少的回溯。只需切换
[]
并测试它:。通常,最好避免使用
*
。顺便说一句,如果您想更好地理解正则表达式,请看:。由于第一行的原因,我无法+1这个答案。不过,原因是回溯是正确的。为了在这个微优化中获得尽可能好的结果,值得添加所有格量词,我更喜欢“狗屎版”。@VisioN:我不想冒犯任何人。所以是敏感的。@Lindrian:(但是,是的,js不支持所有格量词)
var re1 = /\<([^>]*)>/,
    re2 = /\[([^\]]*)\]/;

var address = email.match(re1)[1],
    uname = email.match(re2)[1]; // to avoid `window.name` conflict