2017-08-04 141 views
0

我正在解决一个需要替换负的正则表达式的问题。在javascript中替换负数正则表达式的函数

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

我想有一个negativeReplace函数替换所有text串通过应用匹配re模式子串转换功能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为此,我怎样才能改善我的代码)。

非常感谢。

+0

链接的帖子并不是真正的“负面”正则表达式,因为该解决方案使用正则匹配个别字符的正则表达式进行替换。您的要求并不属于同一类别。 – nnnnnn

+0

您是否需要为*特定表达式*或* any *表达式执行此操作?而且你正在替换*表达式匹配的部分字符串,所以目前还不清楚你在这里做了什么。 –

+0

@ T.J.Crowder在我的问题中,我必须多次使用这个函数。 *这个特定的表达式*仅仅是一个简单的测试用例来描述我的问题。我**做**替换**不匹配**表达式的所有子字符串。请仔细看看我的代码,并且在我写和这篇文章时与一些测试用例一起工作。非常感谢你 –

回答

1

我不能想办法只有.replace()做到这一点,但我可以想办法做到这一点在使用.split().map(),并.join()一个声明。

如果您使用的正则表达式与.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部分。

+0

非常感谢。我用'正则表达式分组'学习'split'的新东西。 –