var email = '[John Smith] <johnsmith@gmail.com>';
var re1 = /.*<+(.*)+>.*/;
var re2 = /.*\[+(.*)+\].*/;
var address = email.replace(re1, "$1");
var name = email.replace(re2, "$1");
我发现第二个正则表达式(获取名称)运行速度非常慢。但第一个很好。为什么会这样,是否有更好的方法来获取我需要的字符串?
你的正则表达式之所以慢是因为它们写得很糟糕。
现在,让我们继续说说它们为什么不好。
您的第一个表达式有一堆 不必要的标记。如前导和尾随.*
- 他们没有区别。其次,你已经量化了<
0 到 inf 次。为什么?你想匹配<<<<<<<<email>
吗?或 email>
?最后,您量化了一个重复组。这太可怕了,因为
- 量化的捕获组会覆盖自己
- 由于上面的陈述,使用捕获组是没有意义的,因此它使用了不必要的资源。
好的,这是第一个表达式。第二个更糟糕,即使你刚刚切换了<>
对于 []
.为什么你会问?我会告诉你为什么。 因为它不匹配。您可能会问,为什么这会如此糟糕?因为它会产生我们所说的灾难性回溯。您可能想知道为什么这样做?我会告诉你原因:
.*
会尽量匹配。事实上,一开始,它会消耗整个字符串。显然失败了,所以它回溯了很多次,直到它可以匹配第一个 [
。 .太棒了,现在引擎已经在字符串的第一个位置找到了文字 [
的匹配项(因此使 .*
不匹配)。现在是下一个标记,.*
由于其贪婪的性质,将再次匹配所有内容。这不起作用,因此引擎回溯。它会一直尝试这样做,直到它匹配字符串。问题是,它永远不会。因为您的贪婪量词被需要 1 个或多个匹配项的量化组包围。
现在,你如何解决这个问题?好吧,你可以简单地删除 +
从小组后面。那会解决它。您的正则表达式仍然很糟糕,但它们不会导致引擎回溯一百万次。我们怎样才能进一步改进它?通过使用否定字符类。
/\[([^]]+)\] <([^>]+)>/
在此处查看正则表达式的演示:http://regex101.com/r/wS2jN0
如果您一开始使用 regex101.com,您会立即注意到回溯问题:http://regex101.com/r/vB8xB0