Regex.prototype.exec在搜索的第二次迭代时返回null

时间:2014-04-25 16:56:16

标签: javascript regex

使用案例

我想在一个字符串中搜索几个匹配项。每个匹配最终链接到对象数组中的对象属性。找到匹配项后,该匹配项将替换为对象中的另一个属性。问题是代码将始终在第二次匹配时返回null。

测试用例

这是我正在使用的测试用例。为了简化问题,我只需用数字5替换所有匹配项,但请注意最终代码将使用变量值替换匹配项。

测试代码

以下是我用于测试和调试问题的代码。有趣的是,如果我更改var str = '5 + QUESTION_2',则QUESTION_2成功替换为5.实际上,问题归结为第二个匹配,即使可以匹配,也始终返回null。

var re = /( |^)(QUESTION_1|QUESTION_2|QUESTION_3)( |$)/g;
var str = 'QUESTION_1 + QUESTION_2';
var rep = 5;

matches = re.exec(str);
var re2 = new RegExp("( |^)(" + matches[2] + ")( |$)", "g");
console.log(matches); // Returns a match on QUESTION_1
str = str.replace(re2, rep);
console.log(str); // Returns 5+ QUESTION_2

matches = re.exec(str);
console.log(matches); // Returns a match on NULL - doesn't find QUESTION_2
re2 = new RegExp("( |^)(" + matches[2] + ")( |$)", "g");
str = str.replace(re2, rep);
console.log(str); // Returns 5+ QUESTION_2

问题

  • 为什么第二场比赛总是空?
  • 此处提供jsfiddle

2 个答案:

答案 0 :(得分:6)

由于您在exec中使用全局标志调用regex引擎会记住lastIndex,它是正则表达式的读/写整数属性,指定开始下一个匹配的索引。

放置此项以重置它:

re.lastIndex=0;

在下次调用RegExp.exec之前

re.lastIndex = 0允许您重置搜索索引以从头开始执行第二次搜索。没有它,搜索从最后一场比赛的索引开始,在这种情况下会产生null

有关详细信息,请阅读此Mozilla doc。根据本手册:

仅当正则表达式使用" g"时才设置此属性。标记以指示全局搜索。

答案 1 :(得分:1)

在全局正则表达式上调用exec时,它会记住最后一个匹配的位置并从那里开始下一个匹配。

var rx = /a/g, matches = rx.exec('aa');
rx.lastIndex; //1

修改输入字符串时,在exec次调用之间,lastIndex会变得不同步。

虽然有一些解决方法,但我宁愿在一个声明中执行替换。

'QUESTION1 + QUESTION2 + QUESTION3'.replace(/QUESTION\d+/g, function ($1) { 
    return 'VALUE_FOR_' + $1; 
});

//"VALUE_FOR_QUESTION1 + VALUE_FOR_QUESTION2 + VALUE_FOR_QUESTION3"