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

IT技术 javascript regex
2021-01-18 05:33:42

在 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”,它就不会发生。

3个回答

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/

@Esalija @squint 这并不完全正确。如果您使用相同的正则表达式来匹配不同的字符串,则lastIndex保留设置为它在第一个字符串中的位置。我今天遇到了这个问题。
2021-03-19 05:33:42
包含while循环示例可能是一件好事,因为这证明了此特定功能的有用性。
2021-03-21 05:33:42
如果有人读到这里,这里有一个小提琴来进一步解释我的困境(上面@squint的回答解释了这一点):jsfiddle.net/grammar/k2hxsq8d/2
2021-03-22 05:33:42
您也可以使用重置它,reg.exec("")因为如果您传递相同的字符串,它只会保留状态
2021-04-12 05:33:42
...哦,您是在谈论 Esailija 的“只有在传递相同字符串时才保留状态”的评论吗?是的,这不对。他的技术将其重置,因为它无法在空字符串中找到匹配项。也许在某些情况下它不会重置?反正我不会使用那种技术。
2021-04-13 05:33:42

来自MDN 文档

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

由于您正在使用该g标志,所以exec从最后一个匹配的字符串开始,直到它结束(返回null),然后重新开始。


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

多场比赛

如果您的正则表达式需要g标志(全局匹配),您将需要使用该lastIndex属性重置索引(最后一个匹配的位置)

reg.lastIndex = 0;

这是因为每次出现exec()都会停止,因此您可以在剩余部分再次运行这种行为也存在于test()) :

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

单场比赛

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