[JS高程] 字元串模式匹配方法
- 2021 年 11 月 25 日
- 筆記
- javascript
1. RegExp 對象
JS 中像其他語言一樣,有正則表達式的支援,即RegExp對象。
該對象主要提供了兩個對象方法,分別是:
exec()
test()
用法示例如下:
let str = "cat bat";
let exp = /.at/g;
exp.exec(str); // ['cat', index: 0, input: 'cat bat', groups: undefined]
exp.exec(str); // ['bat', index: 4, input: 'cat bat', groups: undefined]
exp.exec(str); // null
let str = "cat bat";
let exp = /.at/g;
exp.test(str); // true
更多參看這裡 link
2. 字元串模式匹配方法
但是在處理字元串時,以上方法並不常用,取而代之,String
類型專門為在字元串中實現模式匹配設計了幾個方法。
match()
;search()
;replace()
;
2.1 match()
, search()
其中, match()
和 search()
方法的使用較為類似。 二者的使用示例如下:
let str = "cat, bat, sat, hat";
let pt = /.at/g;
let result = str.match(pt);
console.log(result);
/*
[
"cat",
"bat",
"sat",
"hat"
]
*/
let str = "cat, bat, sat, hat";
let pt = /.at/g;
let result = str.search(pt);
console.log(result); // 0
這兩個方法都是接受一個參數, 是一個 正則表達式字元串,或者RegExp 對象。
所不同的是, match()
返回被匹配的項, 如果是/g
匹配模式,則返回一組包含所有匹配項的數組,否則,返回第一個匹配的到的子串, 其返回解僱結果和exec()
的執行結果相同。 而search()
的返回結果則是首個匹配項的索引值,如果沒有匹配項則返回-1
。
2.2 replace()
重點的需要熟悉replace()
方法, 這是最常用的方法
為了簡化子字元串替換操作,ECMAScript 提供了 replace() 方法。 這個方法接收兩個參數,第一個參數可以是一個RegExp對象,或者一個字元串(這個字元串不會轉換為正則表達式),第二個參數可以是一個字元串或者一個函數。
也就是,repalce()
方法可以單純的用於替換字元串中的子串,也可以用以替換匹配模式匹配的目標子串。
-
替換子字元串,示例:
let str = "cat, bat, sat, hat"; let result = str.replace("at","hello");// chello, bat, sat, hat
⚠️ 注意: 如果第一個參數是字元串,那麼只會替換第一個子字元串。要是想替換所有的子字元串,第一個參數必須為正則表達式並且開啟了全局匹配模式。
-
替換正則匹配項,示例:
let str = "cat, bat, sat, hat"; let pt = /at/g; let result = str.replace(pt,"hello"); console.log(result);// chello, bhello, shello, hhello
2.2.1 第二個參數為字元串的應用情況
第二個參數是字元串的情況下,有幾個特殊的字元序列,可以用來插入正則表達式操作的值。
字元序列 | 替換文本 |
---|---|
$$ |
$ |
$& |
匹配整個模式的子字元串。等同RegExp.lastMatch |
$' |
匹配的子字元串之前的字元串。 —— RegExp.rightContext |
$` |
匹配的子字元串之後的字元串。 —— RegExp。leftContext |
$n |
匹配第 n 個捕獲組的子字元串, n ( 0~9 ), 若沒有捕獲組,值為空串。 |
$nn |
匹配第 nn 個捕獲組, nn (01~99), 若沒有捕獲組,值為空串。 |
以下示例說明:
let str = "I love the moment you smile";
let exp = /I (love (the moment(you)) smile/
該實例中,將會有三個捕獲組:
$$
str.replace(exp,"$$"); // 將匹配到的子串替換為 `$` 符號
// '$'
⚠️ 注意: 儘管是存在捕獲組,但是因為整個模式就能匹配完整的源字元串, 還是直接全部被替換為了 $
符號。
$&
str.replace(exp,"$&"); // 'I love the moment you smile'
$'
、$`
str.replace(exp,"$'"); // ''
str.replace(exp,"$`"); // ''
// "I love the moment you smile "為首個完整匹配,其左側,右側都是空字元
$n
、$nn
str.replace(exp,"$1"); //'love the moment you'
str.replace(exp,"$2"); //'the moment'
str.replace(exp,"$3"); //'you'
注意:
-
以上執行的含義是, 將第二個參數中的字元串,替換掉源字元串中被第一個參數(pattern)所匹配命中的子字元串。
-
以上的示例中,
$'
,$`
的輸出都是空串,以及$$
直接返回$
的原因是,$&
作為整個pattern 命中結果,已經和源字元串相同了,即整個完整的字元串被命中。 如果做以下修改,結果將不同:let str = 'I love the moment you smile';let exp = /love (the moment (you))/;str.replace(exp,"$$")// 'I $ smile'str.replace(exp,"$'")// 'I smile smile'str.replace(exp,"$`")// 'I I smile'
所以, 一點小結: 當字元串方法replace()
的第二個參數為字元串時, replace()
方法的替換目標是 $&
以上述示例來描述,就是 字元串 “I love the moment you smile” 的原始值包裝對象提供的replace()
方法, 在通過正則表達式/love (the moment (you))/
來進行內容替換時, 將會以整個pattern(表達式)匹配到的子串為目標,即 「love the moment you」 為替換目標,也就是$&
。 並無關於pattern 中是否有捕獲組。
2.2.2 第二個參數為函數的應用情況
根據是否有捕獲組,表現不同
replace()
方法第二個參數還支援函數, 目的是用於更加靈活的替換規則,拓展捕獲組的使用需求等。
該函數根據第一個參數中(pattern) 是否具有捕獲組,函數的傳遞參數也不同:
- 沒有捕獲組時 : 函數收到3個參數 :①. 與整個模式匹配的字元串 ②. 匹配項在字元串中的開始位置 ③. 整個字元串
- 有捕獲組時 : 每個匹配捕獲組的字元串都會作為參數傳給這個函數,但是最後兩個參數,依舊是 整個匹配模式開始的位置 和 原始字元串。 因此參數的個數時不確定的,為
n + 2
以下是一些示例:
示例1 :沒有捕獲組:
示例2 : 只有一個捕獲組:
示例3 : 有多個捕獲組:
第二個參數為函數時的字元串替換示例:
示例1:
function htmlEscape(text) {
return text.replace(/[<>"&]/g, function(match, pos, originalText) {
switch(match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "\"":
return """;
}
});
}
console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>"));
// "<p class="greeting">Hello world!</p>"
❓ 這個地方存在一個疑問:
不知道當Pattern 中含有捕獲組的時候要怎麼去處理, 例如:
let str = "i always love the way you lie";
let exp = /always (love) the way (you) lie/;
let res = str.replace(exp, function (...args) {
for (let i = 0; i < args.length; i++) {
if (args[i] === "love") {
return "hate";
} else if (args[i] === "you") {
return "he";
}
}
});
console.log(res); //i hate
期望是將源字元串中的 “love”->”hate”, “you” -> “she” 。
//stackoverflow.com/questions/70105383/how-to-use-while-replace-methods-second-parameter-is-a-function-and-the-sam