在javascript中替换负正则表达式的函数

时间:2017-08-04 02:36:59

标签: javascript regex

我正在处理一个需要替换负正则表达式的问题。

如果我有字符串text,正则表达式模式re和转换函数f

我想要一个negativeReplace函数,通过应用转换函数将所有不匹配子字符串替换为re字符串中的text模式f,剩下的就是其余的。

# input
var text = " aa ( bb ) cc ";
var re = /[\(].*?[\)]/g;
var f = function(s){ return s.toUpperCase() }
# expected output
negativeReplace(text, re, f)
# -> " AA ( bb ) CC "

到目前为止,这是我最好的尝试

function negativeReplace(text, re, f){
  var output = ""
  var boundary = 0;
  while((match = re.exec(text)) != null){
    output += f(text.slice(boundary, match.index)) + match[0];
    boundary = match.index + match[0].length;
  }
  output += f(text.slice(boundary, text.length));
  return output;
}

有效!



function negativeReplace(text, re, f){
  var output = ""
  var boundary = 0;
  while((match = re.exec(text)) != null){
    output += f(text.slice(boundary, match.index)) + match[0];
    boundary = match.index + match[0].length;
  }
  output += f(text.slice(boundary, text.length));
  return output;
}

var text1 = " aa ( bb ) cc ";
var text2 = " aa { bb } cc { dd } ee ";

var f1 = function(s){ return s.toUpperCase() }
var f2 = function(s){ return "_" + s + "_" }

re = /[\({].*?[\)}]/g

console.log(negativeReplace(text1, re, f1)) // AA ( bb ) CC 
console.log(negativeReplace(text2, re, f1)) // AA { bb } CC { dd } EE 
console.log(negativeReplace(text1, re, f2)) // _ aa _( bb )_ cc _
console.log(negativeReplace(text2, re, f2)) // _ aa _{ bb }_ cc _{ dd }_ ee 




然而,我的工具似乎太复杂了。因为javascript已经具有<{>}匹配模式的replace功能。简单的negative regex例如替换为空白的除了数字之外的所有字符,this post中有解决方案。

所以我的问题是如何更好地解决这个问题(我可以使用replace,如何改进我的代码)。

非常感谢你。

1 个答案:

答案 0 :(得分:1)

我想不出只用.replace()做到这一点的方法,但我可以想出一种方法,可以使用.split(),{ {3}}和.map()

如果与.split()一起使用的正则表达式具有捕获括号,则匹配的文本将包含在结果数组中,因此基本上所有具有偶数索引的数组元素都将是与正则表达式不匹配的位,所有具有奇数索引的元素都是与正则表达式匹配的位。所以:

function negativeReplace(str, re, f) {
  return str
    .split(re)
    .map(function(v, i) { return i % 2 === 0 && v ? f(v) : v })
    .join("")
}

var text1 = " aa ( bb ) cc ";
var text2 = " aa { bb } cc { dd } ee ";
var text3 = " aa { bb }{ dd } ee "; // example with no text between two matching substrings

var f1 = function(s){ return s.toUpperCase() }
var f2 = function(s){ return "_" + s + "_" }

re = /([\({].*?[\)}])/        // <--- Note the added parens

console.log(negativeReplace(text1, re, f1)) // AA ( bb ) CC 
console.log(negativeReplace(text2, re, f1)) // AA { bb } CC { dd } EE 
console.log(negativeReplace(text1, re, f2)) // _ aa _( bb )_ cc _
console.log(negativeReplace(text2, re, f2)) // _ aa _{ bb }_ cc _{ dd }_ ee _
console.log(negativeReplace(text3, re, f2)) // _ aa _{ bb }{ dd }_ ee _

编辑:请注意,i % 2 === 0 && v测试包含&& v,因为如果正则表达式匹配两个相邻的子字符串,那么.split()将为这两个匹配项之间的文本返回一个空字符串,而我我假设您不想在这些空字符串上调用转换函数。显然,如果您想要转换空字符串(例如,您的f2()函数会在"__"示例中插入text3),那么只需删除&& v部分。