为什么 Javascript 的 regex.exec()不总是返回相同的值?

在 Chrome 或 Firebug 控制台:

reg = /ab/g
str = "abc"
reg.exec(str)
==> ["ab"]
reg.exec(str)
==> null
reg.exec(str)
==> ["ab"]
reg.exec(str)
==> null

Exec 是否有状态并且取决于它上次返回的内容?还是说这只是个窃听器?我不可能每次都这样。例如,如果上面的“ str”是“ abc abc”,它就不会发生。

53293 次浏览

JavaScriptRegExp对象是有状态的。

当正则表达式是全局的时候,如果您对同一个正则表达式对象调用一个方法,它将从最后一次匹配结束后的索引开始。

当找不到更多的匹配项时,索引将自动重置为 0


若要手动重置,请设置 lastIndex属性。

reg.lastIndex = 0;

这可能是一个非常有用的特性。如果需要,可以在字符串中的任何点启动计算,如果在循环中,则可以在所需的匹配次数之后停止计算。


下面演示在循环中使用正则表达式的一种典型方法。通过将赋值作为循环条件执行,它利用了当没有更多匹配时 exec返回 null这一事实。

var re = /foo_(\d+)/g,
str = "text foo_123 more text foo_456 foo_789 end text",
match,
results = [];


while (match = re.exec(str))
results.push(+match[1]);

演示: http://jsfiddle.net/ppw8y/


如果你不喜欢作业的位置,循环可以重写,比如这个..。

var re = /foo_(\d+)/g,
str = "text foo_123 more text foo_456 foo_789 end text",
match,
results = [];


do {
match = re.exec(str);
if (match)
results.push(+match[1]);
} while (match);

演示: http://jsfiddle.net/ppw8y/1/

来自 MDN 文件:

如果正则表达式使用“ g”标志,则可以多次使用 exec 方法来查找同一字符串中的连续匹配项。当您这样做时,搜索从正则表达式的 lastIndex 属性指定的 str 的子字符串开始(test 也将推进 lastIndex 属性)。

由于您使用的是 g标志,因此 exec将从最后一个匹配的字符串继续到最后(返回 null) ,然后重新开始。


就我个人而言,我更喜欢 str.match(reg)的反面

多处匹配

如果正则表达式需要 g标志(全局匹配) ,则需要使用 lastIndex属性重置索引(上次匹配的位置)。

Reg.lastIndex = 0;

这是因为 exec()在每次发生时停止,这样就可以在剩下的部分上再次运行。这种行为也存在于 test()中) :

如果正则表达式使用“ g”标志,则可以使用 exec 方法多次查找同一字符串中的连续匹配。 指定的 str 的子字符串开始搜索 正则表达式的 lastIndex 属性(test 也将提前 LastIndex 属性)

单场比赛

当只有一个可能的匹配时,您可以简单地通过 省略 g标志重写正则表达式,即 索引将自动重置为 0