为什么这个点不贪心?

时间:2013-09-13 18:36:00

标签: javascript regex

我不明白为什么这个正则表达式中的.不会贪婪地匹配整个字符串:

var re = /.+b/g,
    st = "aaaaaabcd";

console.log( st.match(re) ); //["aaaaaab"]

http://jsbin.com/UmOraTI/1/edit?js,output

我一直试图了解贪婪,似乎.+应与所有字符匹配,因为.基本匹配所有内容。它与*相同。有人可以解释一下吗?

4 个答案:

答案 0 :(得分:7)

.+可以匹配整个字符串,但随后的b将无法匹配。贪婪匹配意味着它会尽可能地匹配,同时仍然可以使其后的模式成功匹配。

答案 1 :(得分:2)

好吧,.+确定 贪婪......你只是不它!

正则表达式引擎会匹配字符串中的所有字符d,并且在那里找到b,但它无处可寻。

因此它返回一个字符(称为回溯),现在介于cd之间,并再次尝试匹配b,但没有成功(d在前面,而不是b)。

它再次回溯到bc之间,但又失败了。

它再次回溯并介于ab之间并最终匹配!这就是它停止回溯并返回你看到的结果的地方。

这就是你得到的原因:

var re = /.+b/g,
    st = "aaaaaabcdbaa";

console.log( st.match(re) ); //["aaaaaabcdb"]

在最后2 a之后回溯,并在 last b匹配。

这是贪婪!

...相反地

var re = /.+?b/g,
    st = "aaaaaabcdbaa";

console.log( st.match(re) ); //["aaaaaab"]

这是懒惰。

有些引擎有运营商来防止这种回溯,这个过程通常会使正则表达式非常缓慢;想象不得不在一个字符串中回溯很多次(通常有很多.*)。

答案 2 :(得分:0)

实际上,在某种程度上, 匹配整个字符串。您的正则表达式匹配器执行称为回溯的操作,这会导致它备份,直到找到适当的匹配项。所以用你的表达:

/.+b/

比赛是这样的:

    aaaaaabcd
.+  ---------
b            x

然后它发现它与be不匹配,因此.+术语“放弃”其中一个匹配,并且mather再次尝试:

    aaaaaabcd
.+  --------
b           x

仍然没有匹配,所以它放弃了另一个,(这将无济于事),另一个,直到它达到这个状态:

    aaaaaabcd
.+  ------
b         -

这是正则表达式的最长匹配。

答案 3 :(得分:0)

var re = /<tr>.*<\/tr>/g,
    st = "<tr>asdf</tr>blah<tr>asdf</tr>";

console.log( st.match(re) );

你必须小心使用正则表达式中的贪婪匹配。上面的例子仍然匹配整个字符串。取自你的jsbin。