多次执行相同的正则表达式匹配时,我看到了一个奇怪的行为:
var r = /(.*)/g
var d = "a"
console.log(r.exec(d))
console.log(r.exec(d))
这会产生:
["a", "a"]
["", ""]
为什么它第二次不匹配任何东西?
多次执行相同的正则表达式匹配时,我看到了一个奇怪的行为:
var r = /(.*)/g
var d = "a"
console.log(r.exec(d))
console.log(r.exec(d))
这会产生:
["a", "a"]
["", ""]
为什么它第二次不匹配任何东西?
这就是g
旗帜的作用。当您使用它时, exec 将从上一个匹配的末尾继续下一个搜索。但是在您的第一个匹配 ( a
) 之后,字符串中没有任何内容,因此您得到一个空匹配。此空匹配通常用于终止exec
-loop。如果您知道只有一个匹配项,请删除g
(这意味着“全局”搜索)。
请注意,您可以(并且应该)摆脱这些括号。它们只会让你付出代价。没有它们,您将只能a
在结果数组中得到一个。
如果您确实想考虑多个匹配项,但忽略最后一个空匹配项,请使用循环技术:
var match;
while(match = r.exec(d))
// process match[0] here
请注意,如果您确实有(有意义的)捕获组,则仅需要此循环。如果没有(如果您只想获得完全匹配),您可以使用match
elclanrs 指出的:
var matches = d.match(r);
编辑:
我才意识到,我所说的大部分内容都是部分正确的,但不是真正的原因["", ""]
。真正发生的是:第一次.*
匹配a
。引擎在上一次匹配之后(之后a
)第二次尝试继续搜索。由于您的模式有.*
(这意味着 0 个或更多字符),它现在将继续匹配空字符串(因为它们与模式匹配)。并且匹配一个空字符串也不会提高下一次搜索的位置。因此,即使有.match
你也会得到["a", ""]
(match
在这种情况下足够聪明地中止)。
实际上,如果您使用带有循环技术的正则表达式,您将得到一个无限循环(因为match = ["", ""]
显然不会导致循环终止)。但无论如何,你应该意识到你的模式是荒谬的,因为*
. 它可以匹配任何东西(包括任何东西)。至少使用.+
. 无论出于何种目的。
exec
返回第一个匹配项并将内部指针向前移动。这样,第二次调用将返回第二次匹配。
由于只有一个匹配项,因此第二次调用返回一个空结果。