正則的一些補充學習
match
, matchAll
和 exec
的差別
match
matchAll
exec
- match,matchAll作用在字元串上,exec作用在正規表達式上
-
match比對g模式的正則時傳回的是比對到的所有字元組成的數組;
比對非g模式的正則時傳回的數組的第一個是比對到的,其餘的是括号裡捕獲到的字元串。
-
exec比對g模式的正則時傳回的數組和match比對的非g模式正則傳回值相同;
在g模式下,exec會記錄比對,會将上次成功比對後的位置記錄在正規表達式的
屬性中,下一次比對會從那開始。lastIndex
- matchAll隻能比對g模式,且傳回一個疊代器,可以通過
來操作,它的傳回值收內建數組和exec是一樣的傳回,都是match比對到非g模式時的傳回值。for...of Array.from 擴充運算符
let str = "abcde abcde abcd";
const Aregexp = /(abc)d(e)/g;
const Bregexp = /(abc)d(e)/;
console.log(str.match(Aregexp)); //? [abcde abcde]
console.log(str.match(Bregexp)); //? [abcde abc e]
console.log(Aregexp.exec(str)); //? [abcde abc e]
console.log(Aregexp.exec(str)); //? [abcde abc e]
console.log(Aregexp.exec(str)); //? null
console.log(Bregexp.exec(str)); //? [abcde abc e]
console.log(Bregexp.exec(str)); //? [abcde abc e]
console.log(...str.matchAll(Aregexp)); //? [abcde abc e] [abcde abc e]
console.log(...str.matchAll(Bregexp)); //! error 隻能比對g模式
(?:x)
非捕獲括号
(?:x)
這與正則的比對無關,遇到的時候可以直接忽略該符号,直接用裡面的字元與後面的拼接。
let str = "abcdbd";
const Aregexp = /(?:abc)d/;
const Bregexp = /abcd/;
console.log(str.replace(Aregexp, "")); //? bd
console.log(str.replace(Bregexp, "")); //? bd
兩個結果是一樣的。
但是比對的結果是不同的,被
(?:)
括起來的不會被exec、match單獨比對出來:
let str = "abcdb";
const Aregexp = /(?:abc)(d)b/;
const Bregexp = /(abc)(d)b/;
console.log(Aregexp.exec(str)); //? abcdb b
console.log(Bregexp.exec(str)); //? abcdb abc d
這個符号是括号的一種特殊形式,一般的括号括起來組成的組會被以
$n
的形式記錄,友善使用,但是用這個符号括起來的組不會被記錄:
let str = "abcdbd";
const Aregexp = /(?:abc)(d)b\1/; //! `\x`會被認為是第x個括号裡的内容 這裡相當于\abcdbabc\
const Bregexp = /(abc)(d)b\1/; //! 這裡相當于\abcdbabc\
console.log(str.replace(Aregexp, "")); //? 空 都替換掉了 因為`(?:)`不會被記錄
console.log(str.replace(Bregexp, "")); //? abcdbd
let strs = "abcdbabc";
console.log(strs.replace(Bregexp, "")); //? 空 都替換掉了
//! 同理 replace 中的 $x也不會記錄
console.log(str.replace(Aregexp, "$2 $1")); //? $2 d
console.log(strs.replace(Bregexp, "$2 $1")); //? d abc
(?<name>)
具名組比對符
(?<name>)
這個符号和上面的
(?:)
一樣是括号的特殊修飾符,它會在比對結果中生成一個
groups
屬性,用對象的鍵值對來記錄括号裡比對的結果:
let str = "abcdb";
const Aregexp = /(?<first>abc)(?<secend>d)/;
console.log(Aregexp.exec(str));
/*
groups:{
first:"abc",
secend:"d",
}
*/
這個比對形式在需要替換多個可能字元時很有用。
先看看
replace
的第二個參數,它可以接收一個回調函數,該函數的傳回值是每個比對項被替換的字元串:
let str = "abcdb"
const Bregexp = /abc/;
console.log(
str.replace(Bregexp, () => {
return "";
})
); //? bd
這個函數接收的參數有多個,詳見MDN,可以使用解構操作符将groups取出:
let str = "abcabcdb";
const Aregexp = /(?<first>abc)|(?<secend>d)/g;
const result = str.replace(Aregexp, (...arg) => {
const groups = JSON.parse(JSON.stringify(arg.pop())); //! 這樣可以删除沒有比對到的空屬性
if (groups.first) {
return "zzz";
} else if (groups.secend) {
return "ddd";
}
});
console.log(result); //? zzzzzzdddb