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