仅替换全局正则表达式

时间:2017-07-26 21:15:44

标签: javascript regex replace

我正在编写一个函数来递归替换字符串中正则表达式的匹配。替换可以是一个函数,就像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标志)。

1 个答案:

答案 0 :(得分:2)

似乎最好的方法是从正则表达式手动删除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;
}