我怎么知道一个字符串中替换了多少个匹配项?

时间:2018-10-16 00:06:37

标签: javascript regex lookbehind

假设我有一个看起来像这样的函数:

function countReplacements ( string, search, replacement ) {
    string.replace ( search, replacement );
}

什么是最干净,最可靠的方法来知道将多少匹配替换为字符串?

我想到了以下可能的解决方案:

  • 用代理服务器包装replacement值,该代理服务器每次访问其代理值时都会记录一次。但是,这不能移植到旧版本的JS。

  • 重新实现String.prototype.replace中使用的算法,以便每次替换该算法时都会记录此内容。这根本不是很干净。

  • 如果search是字符串或非全局正则表达式,我可以检查string是否包含/匹配它。但是,如果search是全局正则表达式,那么当JS将支持lookbehinds时,我不确定这是否行得通,也许所有匹配都在实际替换它们之前就已经计算了?如果不是这种情况,则任何替换都可能导致以下回溯不再匹配,或者现在匹配原始字符串中不匹配的内容。

您认为什么是解决问题的最佳方法?

1 个答案:

答案 0 :(得分:1)

对于替换为字符串的普通情况,对于.replace的第二个参数,请使用回调函数,而不要使用普通的replacement字符串,并使回调增量为变量:

function countReplacements(string, search, replacement) {
  let count = 0;
  const result = string.replace(search, () => {
    count++;
    return replacement;
  });
  return { count, result };
}

console.log(countReplacements('foobar', /o/g, 'a'));

对于更复杂的情况,当replacement是一个函数或包含组引用的字符串时,您将不得不自己重新实现String.prototype.replace:使用提供给{{1 }}获得完整的比赛和分组:

.replace

更懒惰但更易于实现的版本只是调用function countReplacements(string, search, replacement) { let count = 0; const result = string.replace(search, (match, ...groups) => { count++; return replacement .replace(/\$(\d+|&)/g, (_, indicator) => { if (indicator === '&') return match; if (/^\d+$/.test(indicator)) return groups[indicator - 1]; // and so on for other `$`s }); }); return { count, result }; } console.log(countReplacements ( 'foobar', /(o)/g, '$1_' ));并检查结果match,尽管这将需要使用正则表达式两次遍历字符串

length

  

如果搜索是字符串或非全局正则表达式,我可以检查字符串是否包含/匹配它。但是,如果搜索是一个全局正则表达式,那么当JS将支持lookbehinds时,我不确定是否可以正常工作,也许所有匹配项都在实际替换它们之前进行了计算?如果不是这种情况,则任何替换都可能导致以下回溯不再匹配,或者现在匹配原始字符串中不匹配的内容。

这不会有问题-除了function countReplacements(string, search, replacement) { const match = string.match(search); const count = match ? match.length : 0; const result = string.replace(search, replacement); return { count, result }; } console.log(countReplacements ( 'foobar', /(o)/g, '$1_' ));之外,使用.match获取计数的唯一问题是它需要两次遍历字符串。字符串的替换全部一次计算,环顾四周是原始字符串。然后,一旦找到所有匹配项并计算了替换项,则将每个匹配的子字符串替换为其替换项。