提问人:droptix 提问时间:9/21/2023 更新时间:9/21/2023 访问量:45
正则表达式完美匹配,但在替换时跳过匹配
RegEx matches perfectly but skips matches when replacing
问:
我有一个包含占位符的文本,例如.%%%NAME.suffix|DefaultValue%%%
以下正则表达式与它完美匹配(见链接):%{3}((\w+)(?:\.(\w+))?)(?:\|([\s\S]*?))?%{3}
但是当我使用 while 循环在 JavaScript(ES5,ES6 或更高版本中相同)中逐个替换它们时,它会跳过匹配项。
我没有使用 RexEx 模式,而是使用一个简单的字符串。String.replace(/a/gm, "b")
String.replace("%%%NAME.suffix|DefaultValue%%%", "DefaultValue")
var soup = "%%%X.x|a%%% %%%Y.y|b%%% %%%Z.z|c%%%";
var m;
while ((m = regex.exec(soup)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
console.log(m[2] + " found: " + JSON.stringify(m, null, 2));
soup = soup.replace(m[0], m[4]);
}
结果:跳过占位符。为什么?Y
输出:
X found: [ "%%%X.x|a%%%", "X.x", "X", "x", "a" ]
Z found: [ "%%%Z.z|c%%%", "Z.z", "Z", "z", "c" ]
另请参阅此处的完整代码:https://runjs.co/s/IcNbKwSCu
答:
1赞
Alexander Nenashev
9/21/2023
#1
当您在正则表达式时修改字符串时,您将开始在每个循环中正则表达式一个新字符串。这似乎相当混乱。
使用 的迭代器:.matchAll()
更新
由于 OP 声明仅支持 es5,因此只需对字符串的副本执行:
var regex = /%{3}((\w+)(?:\.(\w+))?)(?:\|([\s\S]*?))?%{3}/g;
var soup = "%%%X.x|a%%% %%%Y.y|b%%% %%%Z.z|c%%%";
var soupCopy = soup;
var m;
while(m = regex.exec(soupCopy)){
console.log(m[2] + " found: " + JSON.stringify(m));
soup = soup.replace(m[0], m[4]);
}
console.log(soup);
与捕获组引用相同:
const regex = /%{3}((\w+)(?:\.(\w+))?)(?:\|([\s\S]*?))?%{3}/g;
var soup = "%%%X.x|a%%% %%%Y.y|b%%% %%%Z.z|c%%%";
console.log(soup.replace(regex, '$4'));
评论
0赞
droptix
9/21/2023
好!似乎有效,但不幸的是仅在 ES6+ 中。我的应用程序使用基于 ES5 的 Rhino JS 引擎运行,因此不可用:-(String.matchAll
1赞
droptix
9/21/2023
尊!如此简单和有效:非常感谢!更新的代码示例:runjs.co/s/YEcX7341v
评论
.replace
soup = soup.replace(regex, '$4')
const regex = /%{3}((\w+)(?:\.(\w+))?)(?:\|([\s\S]*?))?%{3}/g