Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Regex.prototype.exec在第二次迭代搜索时返回null 用例_Javascript_Regex - Fatal编程技术网

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

Javascript Regex.prototype.exec在第二次迭代搜索时返回null 用例,javascript,regex,Javascript,Regex,我想在字符串中搜索几个匹配项。每个匹配最终都链接到对象数组中的对象特性。找到匹配项后,该匹配项将替换为对象中的另一个属性。问题是代码在第二次匹配时总是返回null 测试用例 这是我正在使用的测试用例。为了简化问题,我只是将所有匹配项替换为数字5,但请注意,最后的代码将用变量值替换匹配项 测试代码 下面是我用来测试和调试问题的代码。有趣的是,如果我更改var str='5+问题2',问题2将成功地替换为5。本质上,问题归结为第二个匹配始终返回null,即使它可以匹配 var re = /( |^)

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

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

测试代码 下面是我用来测试和调试问题的代码。有趣的是,如果我更改var str='5+问题2',问题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
问题 为什么第二个匹配项总是空的? 可以在这里找到。
因为您在exec call regex引擎中使用的是global flag,所以它会记住lastIndex,lastIndex是正则表达式的读/写整数属性,用于指定开始下一次匹配的索引

放置此按钮可将其重置:

re.lastIndex=0;
在下一次调用RegExp.exec之前

re.lastIndex=0允许您重置搜索索引,以便从头开始执行第二次搜索。如果没有它,搜索将从最后一个匹配的索引开始,在这种情况下将产生null

阅读此文章了解更多信息。根据本手册:


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

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

var rx = /a/g, matches = rx.exec('aa');
rx.lastIndex; //1
在exec调用之间修改输入字符串时,lastIndex将被取消同步

虽然有几种方法可以解决这个问题,但我宁愿在一条语句中执行replace

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

//"VALUE_FOR_QUESTION1 + VALUE_FOR_QUESTION2 + VALUE_FOR_QUESTION3"

选择的答案正确地指出了这个问题,但是我相信你应该按照我的建议去做,而不是依赖于多个执行者和调整lastIndex。有趣的解决方案。我得好好玩玩这个。实际代码中的用例稍微复杂一些,但我认为这可以利用,并且可以简化我的生产问题。在生产问题中,替换也是可变的,我刚才使用了问题??简化它。然而,对于这个特定的测试用例,这是一个更加优雅的解决方案+1。@先生,你的意思是,根据上一次的匹配,必须替换的内容可能会有所不同?如果你能解释你真正的问题,也许我能帮你找到一个有效的解决方案。我只是想让你知道你的解决方案是黄金。比原来的循环解决方案更优雅。非常感谢你的帮助。我希望我能接受这两个答案。@rampage先生,听到这个我很高兴。不幸的是,这是不可能的,你必须选择一个更好地回答这个问题。不仅是为了你,也为了别人;我只想说,将lastIndex设置回0可能会起作用,但并非在所有情况下都有效,因为它将在字符串的开头再次开始匹配。根据你的替代品,它可能会产生异常行为。