Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.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+QUESTION_2',QUESTION_2将成功地替换为5。本质上,问题归结为第二个匹配始终返回null,即使它可以匹配 v

我想在字符串中搜索几个匹配项。每个匹配最终都链接到对象数组中的对象特性。找到匹配项后,该匹配项将替换为对象中的另一个属性。问题是代码在第二次匹配时总是返回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
问题:
  • 为什么第二个匹配项总是空的
  • 可以在这里找到

因为在exec call regex engine中使用全局标志,所以它会记住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
。有趣的解决方案。我得好好玩玩这个。实际代码中的用例稍微复杂一些,但我认为这可以利用,并且可以简化我的生产问题。在生产问题中,替换也是可变的,我只是使用了
QUESTION\uz?
来简化它。然而,对于这个特定的测试用例,这是一个更加优雅的解决方案+1。@先生,你的意思是,根据上一次的匹配,必须替换的内容可能会有所不同?如果你能解释你真正的问题,也许我能帮你找到一个有效的解决方案。我只是想让你知道你的解决方案是黄金。比原来的循环解决方案更优雅。非常感谢你的帮助。我希望我能接受这两个答案。@rampage先生,听到这个我很高兴。不幸的是,这是不可能的,你必须选择一个更好地回答这个问题。不仅是为了你,也为了其他人;)我只想说,将
lastIndex
设置回
0
可能会起作用,但不是在所有情况下都会起作用,因为它会在字符串的开头再次开始匹配。根据你的替代品,它可能会产生异常行为。