我正在编写一个函数以递归方式替换字符串中正则表达式的匹配项。替换可以是一个函数,就像vanilla .replace
一样,该函数可以通过其参数之一访问原始字符串。
我希望我的函数在每次迭代中只替换一个匹配项。对于非全局正则表达式,情况总是如此。但是,此函数接收的某些正则表达式将是全局的。进行传统的.replace(regex, replacement)
意味着它可以在每次迭代中多次替换,不仅会弄乱匹配的处理顺序,而且还会将错误的索引和原始字符串传递给替换函数。
举个例子:
function recursiveReplace(string, regex, replacement) {
for (var i = 1e8; i > 0 && regex.test(string); i--)
string = string.replace(regex, replacement);
return string;
}
console.log(
recursiveReplace("abcdef", /../g, function (match, index, original) {
console.log(original);
return match[0];
})
);
这个输出
abcdef
abcdef
abcdef
ace
ae
a
当所需的输出是
abcdef
acdef
adef
aef
af
a
无论正则表达式是否带有
g
标志,我如何才能使该函数在每次迭代中仅处理一个匹配项?请注意,我以这种方式使用该函数,使得第二个参数将始终为正则表达式(对此我无权控制,也无法控制该正则表达式是否具有g
标志)。 最佳答案
似乎最好的方法是手动从正则表达式中删除g
标志。这是我可以找到的最跨平台的方法,使用regex.toString()
获取正则表达式的字符串表示形式:
function recursiveReplace(string, regex, replacement) {
regex = eval(regex.toString().replace(/[a-z]*$/, function (s) {
return s.replace('g', '');
}));
for (var i = 1e8; i > 0 && regex.test(string); i--)
string = string.replace(regex, replacement);
return string;
}
借助ES6的
RegExp(regex)
和 RegExp#flags
功能,这变得更加容易:function recursiveReplace(string, regex, replacement) {
regex = RegExp(regex, regex.flags.replace('g', ''));
for (var i = 1e8; i > 0 && regex.test(string); i--)
string = string.replace(regex, replacement);
return string;
}
关于javascript - 仅替换全局正则表达式的第一个匹配项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45337572/