【问题标题】:Why does Javascript's regex.exec() not always return the same value? [duplicate]为什么 Javascript 的 regex.exec() 并不总是返回相同的值? [复制]
【发布时间】:2012-07-13 17:07:04
【问题描述】:

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

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    JavaScript RegExp 对象是有状态的。

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

    当找不到更多匹配项时,索引会自动重置为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/

    【讨论】:

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

    多重匹配

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

    reg.lastIndex = 0;

    这是因为exec()stop on each occurence so you can run again on the remaining parttest()) 也存在这种行为:

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

    单场比赛

    当只有一个可能的匹配项时,您可以通过省略g 标志 将正则表达式重写为index will be automatically reset to 0

    【讨论】:

      【解决方案3】:

      来自MDN docs

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

      由于您使用g 标志,exec 从最后一个匹配的字符串继续直到它到达末尾(返回 null),然后重新开始。


      就我个人而言,我更喜欢用str.match(reg)反其道而行之

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-20
        • 1970-01-01
        • 2014-05-18
        • 2018-09-24
        • 2020-04-06
        • 1970-01-01
        • 2011-07-12
        相关资源
        最近更新 更多