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

JavaScript RegExp对象是有状态的。

当正则expression式是全局的,如果你调用一个方法相同的正则expression式对象,它将从索引开始,超过最后一场比赛的结束。

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


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

 reg.lastIndex = 0; 

这可能是一个非常有用的function。 如果需要,您可以在string中的任意位置开始评估,或者如果在循环中,可以在所需数量的匹配之后停止评估。


下面是在循环中使用正则expression式的典型方法的演示。 它利用了这样一个事实,即通过执行作为循环条件的分配,当不存在更多匹配时, 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]); 

DEMO: 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); 

DEMO: http : //jsfiddle.net/pPW8Y/1/

来自MDN文档 :

如果您的正则expression式使用“g”标志,则可以多次使用exec方法在同一个string中查找连续的匹配项。 当你这样做的时候,search从正则expression式的lastIndex属性指定的str的子string开始(test也将提前lastIndex属性)。

由于您使用的是g标志,因此exec从最后一个匹配的string继续,直到到达结尾(返回null ),然后重新开始。


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

多个匹配

如果你的正则expression式需要g标志(全局匹配),你将需要通过使用lastIndex属性重置索引(最后匹配的位置)。

reg.lastIndex = 0;

这是由于exec()会在每个事件中停止,所以你可以在剩下的部分再次运行 。 这个行为在test()也存在:

如果您的正则expression式使用“g”标志,则可以多次使用exec方法在同一个string中查找连续的匹配项。 当你这样做的时候,search从正则expression式的lastIndex属性指定的str的子string开始(test也将提前lastIndex属性)

单一匹配

当只有一个可能的匹配时,你可以简单地通过忽略g标志来重写你的正则expression式,因为索引将被自动重置为0