2

多次执行相同的正则表达式匹配时,我看到了一个奇怪的行为:

var r = /(.*)/g
var d = "a"

console.log(r.exec(d))
console.log(r.exec(d))

这会产生:

["a", "a"]
["", ""]

为什么它第二次不匹配任何东西?

4

2 回答 2

7

这就是g旗帜的作用。当您使用它时, exec 将从上一个匹配的末尾继续下一个搜索。但是在您的第一个匹配 ( a) 之后,字符串中没有任何内容,因此您得到一个空匹配。此空匹配通常用于终止exec-loop。如果您知道只有一个匹配项,请删除g(这意味着“全局”搜索)。

请注意,您可以(并且应该)摆脱这些括号。它们只会让你付出代价。没有它们,您将只能a在结果数组中得到一个。

如果您确实想考虑多个匹配项,但忽略最后一个空匹配项,请使用循环技术:

var match;
while(match = r.exec(d))
    // process match[0] here

请注意,如果您确实有(有意义的)捕获组,则仅需要此循环。如果没有(如果您只想获得完全匹配),您可以使用matchelclanrs 指出的:

var matches = d.match(r);

编辑:

我才意识到,我所说的大部分内容都是部分正确的,但不是真正的原因["", ""]。真正发生的是:第一次.*匹配a。引擎在上一次匹配之后(之后a)第二次尝试继续搜索。由于您的模式有.*(这意味着 0 个或更多字符),它现在将继续匹配空字符串(因为它们与模式匹配)。并且匹配一个空字符串也不会提高下一次搜索的位置。因此,即使有.match你也会得到["a", ""]match在这种情况下足够聪明地中止)。

实际上,如果您使用带有循环技术的正则表达式,您将得到一个无限循环(因为match = ["", ""]显然不会导致循环终止)。但无论如何,你应该意识到你的模式是荒谬的,因为*. 它可以匹配任何东西(包括任何东西)。至少使用.+. 无论出于何种目的。

于 2012-12-13T21:39:00.523 回答
1

exec返回第一个匹配项并将内部指针向前移动。这样,第二次调用将返回第二次匹配。

由于只有一个匹配项,因此第二次调用返回一个空结果。

于 2012-12-13T21:39:20.117 回答