为什么RegExp“贪婪”模式不起作用?

时间:2012-02-03 17:46:55

标签: javascript regex regex-greedy quantifiers

我不明白这种行为。我有这样的例子,需要抓住html评论。

var str = '.. <!--My -- comment test--> ';

var regex1 = /<!--[.]*-->/g;
var regex2 = /<!--.*-->/g;

alert(str.match(regex1));      // null
alert(str.match(regex2));      // <!--My -- comment test--> 

第二个正则表达式regex2工作正常,完全输出所需内容。第一个显示null。我不明白其中的区别。 RegExpressions <!--[.]*--><!--.*-->的含义相同 - “<!--之后的任意字符,除了换行符数量从0到尽可能多,并以-->结束”。但对于第二个它是有效的,而第一个没有。为什么呢?

UPD。 我已阅读评论并有更新。

var str3 = '.. <!--Mycommenttest--> ';
var str4 = '.. <!--My comment test--> ';

var regex3 = /<!--[\w]*-->/g;
var regex4 = /<!--[\s\S]*-->/g;

alert(str.match(regex3));         // <!--Mycommentstest-->
alert(str.match(regex4));         // <!-- My comment test -->

因此可以使用有限的匹配变量来匹配任何内容。那么应该采用哪种方式正确使用RegExps?使用[]或不使用它们?无法得到差异,两者都给出正确的输出。

4 个答案:

答案 0 :(得分:5)

点(.)并不意味着字符类中的“任何东西”。为什么你需要一个字符类来匹配任何东西?

答案 1 :(得分:3)

  

RegExpressions <!--[.]*--><!--.*-->表示相同的

这不正确。

括号[]表示一个字符类,可以匹配类中的任何字符。 [.]是包含“.”字符的字符类。将其与.进行对比,<!--[.]*-->是一个预定义的字符类,用于表示“任何字符”(行终止符除外)。

因此,与.匹配的内容是空注释或完全由“<!--.*-->”字符组成的注释。与{{1}}匹配的内容是空注释或填充除换行符之外的任何字符的注释。

答案 2 :(得分:3)

\w\d\s这样的字符类缩写与内部字符类完全相同,但像.这样的元字符通常在字符类中失去特殊含义。这就是/<!--[.]*-->/无效的原因:[.]与文字.匹配。

但是/<!--.*-->/也不起作用,因为.与换行符不匹配。在大多数正则表达式中,您可以使用单行模式让点匹配所有字符,包括换行符,如下所示:/<!--.*-->/s或此:(?s)<!--.*-->。但JavaScript不支持该功能,因此大多数人使用[\s\S]代替,意思是“任何空白字符或空格”的任何字符 - 换句话说,任何字符。

但那也不对,因为(正如杰森在评论中指出的那样)它会贪婪地匹配从第一个<!--到最后一个-->的所有内容,这可能包含几个单独的评论和所有他们之间没有评论材料。要使它真正正确可能不值得努力。使用正则表达式匹配HTML时,无论如何都必须做出许多简化假设;如果你不能假设一定程度的良好状态,你也可以放弃。在这种情况下,足以使量词非贪婪:

var regex5 = /<!--[\s\S]*?-->/g;

答案 3 :(得分:2)

第一个不是因为它并不意味着相同。第一种匹配句点字符的方法。当置于[]集内时,句点字符不是通用匹配。 (如果你考虑一下,这是有道理的:你为什么要匹配一组有限匹配变量中的任何东西)