2017-08-04 138 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'的新東西。 –