首先介紹一下業務需求:函數
在實時輸入過程當中,&&、||和-三個符號中的任意兩個(包括自身重複在內)不能直接或經過空格連在一塊兒,不然只保留第一個。測試
這是我第一時間想到的方法,窮舉這三個符號任意兩個符號的排列組合,而後一一替換。根據排列組合公式可知一共有6種不一樣的組合方式,須要寫6個正則。
這種方法的好處是易於理解,但缺點也顯而易見,代碼臃腫,難以維護。ui
首先,寫出這個正則spa
let reg = /((&&|\|\||-)\s*){2,}/g
複製代碼
這個正則的意思是,匹配任意這三個符號(&& || -)加零個或多個空格出現兩次以上的文本。
有了這個正則,接下來就是如何替換了,首先想到的是正則的反向引用了$1($1的意思是第一個分組的內容,正則中括號()表明分組,即((&&|\|\||-)\s*)
)code
先來分析一下這個正則的匹配過程,咱們寫個測試案例來演示regexp
'|| -'.replace(/((&&|\|\||-)\s*){2,}/g,"\$1") // -
複製代碼
匹配過程是這樣的:字符串
"|| "
符合第一個分組內容,但不符合{2,}
(出現兩次以上), 此時$1分組的內容是"|| "
"-"
符合規則,此時$1分組的內容是"-"
(&&|\|\||-)\s*)
同時出現兩次以上的規則,開始替換,將整個字符串替換成$1
,即-
,因此輸出爲"-"
那麼問題來了,業務的需求是替換成第一個字符,而咱們卻替換成了最後一個字符。彆着急,先喝口水冷靜一下。其實咱們只要把原字符串翻轉一下,再傳進來不就符合要求了嗎,替換完畢後記得把字符串翻轉回去就好了string
// 翻轉字符串
function rever(str) {
return str.split("").reverse().join("")
}
複製代碼
完整代碼以下:it
let str = 'ccc && ||'
function rever(str) {
return str.split("").reverse().join("")
}
let newStr = rever(rever(str).replace(/((&&|\|\||-)\s*){2,}/g,"\$1"))
console.log(newStr);
複製代碼
代碼寫出來了,測試結果也符合預期,那麼就大功告成了嗎?
看看這段代碼的實現原理,是把原字符串翻轉,而後進行匹配替換,替換完在把字符串翻轉回來。 代碼執行過程當中,是對原字符進行了修改的。若是放到生產環境中,因爲用戶的輸入習慣不一樣,可能會形成某些不可預期的錯誤。io
replace的第二個參數,除了傳入字符串,不是還能夠傳入一個函數嗎?咱們只要在這個函數中,把符合業務須要的第一個字符找出來,而後return 出去,不就完事了嗎?
用這種方式處理,不會污染原字符串,沒有反作用。不知道算不算得上最優解呢?
代碼很簡單,你們看一下應該就明白了:
let str = 'ccc && ||'
let newStr = str.replace(/((&&|\|\||-)\s+){2,}/g, function(a){
return a.substr(0, a.indexOf(' ')) + ' ';
});
console.log(newStr); // "ccc && "
複製代碼
PS:點個贊再走吧~