简体   繁体   English

仅替换全局正则表达式的第一个匹配项

[英]Replacing only the first match of a global regex

I'm writing a function to recursively replace matches of a regex in a string. 我正在写一个函数来递归替换字符串中正则表达式的匹配项。 The replacement can be a function, as with vanilla .replace , and this function can access the original string through one of its arguments. 替换可以是一个函数,就像vanilla .replace ,该函数可以通过其参数之一访问原始字符串。

I would like my function to replace only one match on each iteration. 我希望我的函数在每次迭代中仅替换一个匹配项。 With a non-global regex, this will always be the case. 对于非全局正则表达式,情况总是如此。 However, some of the regexes this function receives will be global. 但是,此函数接收的某些正则表达式将是全局的。 Doing a traditional .replace(regex, replacement) means it could replace multiple times on each iteration, not only messing up the order in which the matches are processed, but also passing an incorrect index and original string to the replacement function. 进行传统的.replace(regex, replacement)意味着它可以在每次迭代中多次替换,不仅弄乱了匹配的处理顺序,而且还向替换函数传递了错误的索引和原始字符串。

As an example: 举个例子:

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];
  })
);

This outputs 这个输出

abcdef
abcdef
abcdef
ace
ae
a

when the desired output is 当所需的输出是

abcdef
acdef
adef
aef
af
a

How can I get the function to process only one match on each iteration, whether the regex has the g flag or not? 无论正则表达式是否带有g标志,如何在每次迭代中仅处理一个匹配项的函数? Note that I'm using the function in such a way that the second argument will always be a regex (I have no control over this, nor over whether or not said regex has the g flag). 请注意,我使用该函数的方式使得第二个参数将始终是一个正则表达式(对此我无权控制,也无法控制所述正则表达式是否具有g标志)。

It would seem that the best way to do this would be to just manually remove the g flag from the regex. 似乎最好的方法是手动从正则表达式中删除g标志。 Here's the most cross-platform way I could find to do this, using regex.toString() to get the string representation of the regex: 这是我可以找到的最跨平台的方法,使用regex.toString()获取regex的字符串表示形式:

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;
}

With the ES6 features RegExp(regex) and RegExp#flags this gets much easier: 借助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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM