前言
本章介紹正則的擴(kuò)展。有些不常用的知識(shí)了解即可。
本章原文鏈接:正則的擴(kuò)展
RegExp 構(gòu)造函數(shù)
從 ES6 開始,如果RegExp
構(gòu)造函數(shù)第一個(gè)參數(shù)是一個(gè)正則對(duì)象,并且第二個(gè)標(biāo)志存在且為標(biāo)志參數(shù),將不再拋出 TypeError
,將使用這些參數(shù)創(chuàng)建一個(gè)新的正則表達(dá)式。原有的正則表達(dá)式修飾符將被忽略
const flag = new RegExp(/[0-9]/ig, i).flags; // 原有修飾符衛(wèi) ig ,被 i 給替代了console.log(flag); // i
字符串有關(guān)正則表達(dá)式
ES6將之前字符串上的四個(gè)關(guān)于正則表達(dá)式的方法全部更改為RegExp
的實(shí)例方法,所以現(xiàn)在所有與正則表達(dá)式有關(guān)的方法,全部定義在RegExp
對(duì)象上。
String.prototype.match
調(diào)用RegExp.prototype[Symbol.match]
String.prototype.replace
調(diào)用RegExp.prototype[Symbol.replace]
String.prototype.search
調(diào)用RegExp.prototype[Symbol.search]
String.prototype.split
調(diào)用RegExp.prototype[Symbol.split]
flags 屬性
RegExp.prototype.flags
屬性 是ES6新增屬性,會(huì)返回正則表達(dá)式的修飾符。
const SAMPLEREG = /abc/ig;console.log(SAMPLEREG.flags); // gi
u 修飾符
在ES6中新增了 u
修飾符,表示使用Unicode
碼的模式進(jìn)行匹配。處理大于/uFFFF
的 Unicode
字符
注意
一旦加上u
修飾符號(hào),就會(huì)修改下面這些正則表達(dá)式的行為。
- 點(diǎn)字符
對(duì)于碼點(diǎn)大于0xFFFF
的 Unicode
字符,點(diǎn)字符不能識(shí)別,必須加上u
修飾符。
**Unicode**
字符表示法
新增了使用大括號(hào)表示 Unicode
字符,這種表示法在正則表達(dá)式中必須加上u
修飾符,才能識(shí)別當(dāng)中的大括號(hào),否則會(huì)被解讀為量詞。
- 量詞
使用u
修飾符后,所有量詞都會(huì)正確識(shí)別碼點(diǎn)大于0xFFFF
的 Unicode
字符。
- 預(yù)定義模式
u
修飾符也影響到預(yù)定義模式,能否正確識(shí)別碼點(diǎn)大于0xFFFF的 Unicode 字符。
i
修飾符
有些 Unicode
字符的編碼不同,但是字型很相近,比如,/u004B
與/u212A
都是大寫的K
- 轉(zhuǎn)義
沒(méi)有u
修飾符的情況下,正則中沒(méi)有定義的轉(zhuǎn)義(如逗號(hào)的轉(zhuǎn)義/,
)無(wú)效,而在u模式會(huì)報(bào)錯(cuò)。
unicode 屬性
RegExp.prototype.unicode
屬性表明正則表達(dá)式帶有"u
" 標(biāo)志。 unicode
是正則表達(dá)式獨(dú)立實(shí)例的只讀屬性。
const SAMPLEREG = /abc/u;console.log(SAMPLEREG.flags); // uconsole.log(SAMPLEREG.unicode); // true
Unicode 屬性類
**Unicode property escapes**
ES2018 引入了一種新的類的寫法/p{...}
和`P{...},用于解決 JavaScript 沒(méi)有強(qiáng)有效的方式用匹配出不同文字問(wèn)題。允許正則表達(dá)式匹配符合
Unicode` 某種屬性的所有字符。
/p{Unicode屬性名=Unicode屬性值}// 對(duì)于某些屬性,可以只寫屬性名,或者只寫屬性值。/p{Unicode屬性值}/p{Unicode屬性名}// /P 為 /p 取反/P{Unicode屬性值}/P{Unicode屬性名}
注意:
這兩種類只對(duì) Unicode
有效,所以使用的時(shí)候一定要加上u
修飾符。/P{…}
是/p{…}
的反向匹配,即匹配不滿足條件的字符。
const SAMPLEREG = //p{Script=Greek}/u;SAMPLEREG.test(π); // true
y 修飾符
y 修飾符的作用
在ES6中新增了 y
修飾符,表示執(zhí)行“粘性(sticky)”搜索,匹配從目標(biāo)字符串的當(dāng)前位置開始。
y
修飾符與g
修飾符相似,都是全局匹配,后一次匹配從上一次匹配成功的下一個(gè)位置開始。
區(qū)別是:g
修飾符只要剩余位置中存在匹配即可;而y
修飾符必須從剩余的第一個(gè)位置開始匹配。
// y修飾符與g修飾符的區(qū)別const SAMPLE = abcdabcd;const SAMPLEREG1 = /abcd/g;const SAMPLEREG2 = /abcda/y;console.log(SAMPLEREG1.test(SAMPLE)); // trueconsole.log(SAMPLEREG2.test(SAMPLE)); // trueconsole.log(SAMPLEREG1.test(SAMPLE)); // trueconsole.log(SAMPLEREG2.test(SAMPLE)); // false
注意
實(shí)際上,y
修飾符號(hào)隱含了頭部匹配的標(biāo)志^
。
const SAMPLEREGGY = /ab/gy;const SAMPLEREGY = /ab/y;let sample1 = ababcabcd.replace(SAMPLEREGGY, -); let sample2 = ababcabcd.replace(SAMPLEREGY, -);// 最后一個(gè)ab因?yàn)椴皇浅霈F(xiàn)在下一次匹配的頭部,所以不會(huì)被替換。console.log(sample1);// 只能返回第一個(gè)匹配,必須與g修飾符聯(lián)用,才能返回所有匹配。console.log(sample2);
sticky 屬性
RegExp.prototype.sticky
表示是否設(shè)置了y
修飾符。sticky
是正則表達(dá)式對(duì)象的只讀屬性。
const SAMPLEREG = /a/gy;console.log(SAMPLEREG.sticky); // true
s 修飾符
ES2018 引入s
修飾符,使得.
可以匹配任意單個(gè)字符。包括行終止符(line terminator character)。
行終止符
所謂行終止符,就是該字符表示一行的終結(jié)。以下四個(gè)字符屬于“行終止符”。
U+000A
換行符(/n
)U+000D
回車符(/r
)U+2028
行分隔符(line separator
)U+2029
段分隔符(paragraph separator
)
const SAMPLEREG = /ab.cd/s;console.log(SAMPLEREG.test(ab/ncd) ); // true
dotAll
上面這種情況被稱為**dotAll**
模式,即點(diǎn)(dot)代表一切字符。正則表達(dá)式還引入了一個(gè)**dotAll**
屬性dotAll
屬性返回一個(gè)布爾值,表明是否在正則表達(dá)式中一起使用"s
"修飾符。dotAll
是一個(gè)只讀的屬性,屬于單個(gè)正則表達(dá)式實(shí)例。
const SAMPLEREG = /ab.cd/s; const sample = SAMPLEREG.test(ab/ncd); console.log(SAMPLEREG.flags); // s console.log(SAMPLEREG.dotAll); // true
后行斷言
ES2018 引入后行斷言,V8 引擎 4.9 版(Chrome 62)已經(jīng)支持。
先行斷言
x
只有在y
前面才匹配,必須寫成/x(?=y)/
。
比如,只匹配百分號(hào)之前的數(shù)字,要寫成//d+(?=%)/
。先行否定斷言
,x
只有不在y
前面才匹配,必須寫成/x(?!y)/
。
比如,只匹配不在百分號(hào)之前的數(shù)字,要寫成//d+(?!%)/
。后行斷言
正好與先行斷言
相反,x
只有在y
后面才匹配,必須寫成/(?<=y)x/
。
比如,只匹配美元符號(hào)之后的數(shù)字,要寫成/(?<=/$)/d+/
。后行否定斷言
則與先行否定斷言
相反,x
只有不在y
后面才匹配,必須寫成/(?<!y)x/
。
比如,只匹配不在美元符號(hào)后面的數(shù)字,要寫成/(?<!/$)/d+/
。
后行斷言需要先匹配/(?<=y)x/
的x
,然后再回到左邊,匹配y
的部分。順序?yàn)?strong>先右后左,
// 先行斷言const sample1 = //d+(?=%)/.exec(100% of US presidents have been male);// 先行否定斷言const sample2 = //d+(?!%)/.exec(that’s all 44 of them);console.log(sample1); // 100console.log(sample2); // 44// 后行斷言const sample3 = /(?<=/$)/d+/.exec(Benjamin Franklin is on the $100 bill);// 后行否定斷言const sample4 = /(?
組匹配
正則表達(dá)式的括號(hào)表示分組匹配,括號(hào)中的模式可以用來(lái)匹配分組的內(nèi)容。
ES2018 引入了具名組匹配(Named Capture Groups),允許為每一個(gè)組匹配指定一個(gè)名字,既便于閱讀代碼,又便于引用。
具名組匹配在圓括號(hào)內(nèi)部,模式的頭部添加“問(wèn)號(hào) + 尖括號(hào) + 組名”(?<year>)
,然后就可以在exec
方法返回結(jié)果的groups
屬性上引用該組名。同時(shí),數(shù)字序號(hào)依然有效。
const sampleUsers = `姓劉名備字玄德姓關(guān)名羽字云長(zhǎng)姓張名飛字翼德`;const SAMPLEREG = /姓(?
上面的代碼中:
?<xxx>
的作用就是為這個(gè)匹配定義一個(gè)組名,在匹配的groups
屬性中可以查看到匹配的組名,這里可以使用解構(gòu)賦值直接從匹配結(jié)果上為變量賦值。
注意 : 如果要在正則表達(dá)式內(nèi)部引用某個(gè)具名組匹配,可以使用
/k<組名>
的寫法
matchAll()
ES2020 增加了
String.prototype.matchAll()
方法,可以一次性取出所有匹配。不過(guò),它返回的是一個(gè)遍歷器/迭代器(Iterator
),而不是數(shù)組。
const string = sample1sample2sample3;const regex = /sample/g;for (const match of string.matchAll(regex)) { console.log(match);}// 遍歷輸出/*[sample, index: 0, input: sample1sample2sample3, groups: undefined][sample, index: 7, input: sample1sample2sample3, groups: undefined][sample, index: 14, input: sample1sample2sample3, groups: undefined]*/