我有一个简单的JavaScript正则表达式检查(由其他开发人员编写),可以完美地处理数千个不同的字符串。但是我刚发现一个特定的字符串值导致正则表达式在Firefox / IE中执行长达10分钟是不可接受的。为方便起见,我已将实际的正则表达式调用解压缩为小代码段:
<html>
<script>
function dodo(){
var mask = /^([\w'#@\-\&\(\)\/.]+[ ]*){1,100}$/;
var value = "Optometrists Association Australia, Queensland/NT Division";
mask.exec(value);
}
</script>
<body>
<input type="button" value="Click" onclick="dodo()">
</body>
</html>
这是什么问题?如果我将值改为其他任何东西,它就能完美地运作。
谢谢!
答案 0 :(得分:6)
你可能意味着在空间组之后有一个+,而不是*。如果用+替换它,事情就会快得多。 *会导致正则表达式评估程序尝试大量的组合,所有这些组合在到达','时都会失败。您可能还想在第一个字符组中添加“,”。
总体而言,它可能如下所示:
var mask = /^([\w'#@\-\&\(\)\/.,]+[ ]+){1,100}$/;
答案 1 :(得分:6)
你正在进行疯狂的回溯,这是正则表达式中的一个常见功能,包括一些形式([字符] +)+ - 它适用于各种匹配模式,但是你会发现像这样的字符串,它使它爆炸,在整个字符串递归。这是一个发生了什么的草图。
首先,您的模式将字符串拆分为组。我使用|
来启动您的群组实例,即您重复的群组{1,100}
。 >
是组的结尾,?
是正则表达式解析器的“游标”。
|----------->|---------->|-------?
Optometrists Association Australia, Queensland/NT Division
在?处,您的模式无法再匹配任何符号或空格,因此它会尝试匹配$。由于光标尚未到达行的末尾,因此它失败,正则表达式解析器回溯:
|----------->|---------->|------?
Optometrists Association Australia, Queensland/NT Division
再一次,它找不到任何空格,因此终止该组,并尝试启动另一个(因为最多可以有100个,到目前为止我们只使用了3个。)
|----------->|---------->|------|-?
Optometrists Association Australia, Queensland/NT Division
解析器再次遇到有问题的,
,它会杀死该执行树,导致它再次回溯到i
中的Australia
。而且,就像上次一样,它试图创建一个小组:
|----------->|---------->|-----|--?
Optometrists Association Australia, Queensland/NT Division
...无论如何,你明白了。这个循环的失败,回溯和切片将再次有效地冻结你的正则表达式解析器,直到每个排列耗尽并返回false。识别和解决这个问题的关键是永远不要重复一个重复的组,在开头和/或结尾没有某种形式的分隔符。我建议使用边界锚\b
这个词,因为[ ]+
会要求你的字符串以空格结尾:
/^(\b[\w'#@\-\&\(\)\/.]+\b[ ]*){1,100}$/
作为旁注,如果没有更多的上下文,很难说你的正则表达式在做什么,但似乎你也可以调用value.split(' ')
将字符串拆分为空格字符,并运行更简单的正则表达式所有这些子串。它消除了对双重正则表达式重复的需要。
答案 2 :(得分:4)
这看起来像一个正则表达式的糟糕应用程序,以及一个糟糕的正则表达式启动。我认为,目的似乎是匹配1到100个以空格分隔的“单词”的列表。以下是我可以看到的核心问题:
在单词的末尾使用“[] *”而不是“[] +”意味着每个字节都可能只是一个“单词”,无论它是否以空格为界。这是你的引擎跟踪的很多匹配案例。
您正在使用捕获括号(“(...)”)而非捕获括号(“(?:...)”)。分组将更多地保存,以保存与您匹配的最后一个单词,您可能需要或不需要。
还有一些小问题:
“[] *”表达式是多余的。只需使用“*”匹配零个或多个空格即可。但是你可能想要“\ s”来匹配任何类型的空格,而不仅仅是空格。
表达式允许字符串末尾的空格,但不允许开头。大多数应用程序通常都希望容忍这两种应用程序,或者两者都不容忍。
为了便于阅读,请勿在不需要的地方使用反斜杠转义。只有括号中的“ - ”才需要它。
100的魔力是什么?你真的想要硬编码这个限制吗?
最后,为什么要在这里使用正则表达式?为什么不简单地将空格上的split()转换为子串数组,然后针对更简单的表达式测试每个结果单词?
答案 3 :(得分:1)
从字符串中删除逗号或将其添加到字符组会使其快速执行,但如果没有正确操作的示例或对您要实现的内容的解释,我无法确定它是否正常工作。 ..