ES9中正則表達式相關主要有兩個提案:正則表達式命名捕獲組 & 正則表達式dotAll模式,目前都已進入stage4階段。html
ECMAScript提案「正則表達式命名捕獲組」proposal-regexp-named-group 由 Gorkem Yakin, Daniel Ehrenberg負責。java
捕獲組就是把正則表達式中子表達式匹配的內容,保存到內存中以數字編號或顯示命名的組裏,方便後面引用,且這種引用既能夠在正則表達式內部,也能夠在正則表達式外部。git
捕獲組有兩種形式,一種是普通捕獲組,另外一種是命名捕獲組。github
目前JavaScript只支持數字形式的普通捕獲組,而這個提案就是爲了給JavaScript增長命名捕獲組。正則表達式
編號規則指的是以數字爲捕獲組進行編號的規則, 編號0的捕獲組表明正則表達式總體。babel
const regex = /(\d{4})-(\d{2})-(\d{2})/; const matchers = regex.exec('2020-12-02'); console.table(matchers)
使用數字捕獲組的一個缺點是對於引用不太直觀。好比上面的例子,咱們相對比較難分清楚哪一個組表明年,哪一個組表明月或者日。並且,當咱們交互了年和月的值時,使用捕獲組引用的代碼都須要更改。app
而命名捕獲組就是爲了解決這個問題。函數
命名捕獲組可使用(?<name>...)語法給每一個組起個名稱。所以,用來匹配日期的正則表達式能夠寫爲:spa
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
每一個捕獲組的名字必須惟一,不然會拋出異常:
另外,捕獲組的名字必須符合JavaScript命名規範:prototype
命名捕獲組能夠經過匹配結果的groups
屬性訪問。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; let result = regx.exec('2020-12-02'); result.groups.year === '2020'; result.groups.month === '12'; result.groups.day === '02'; result[0] === '2020-12-02'; result[1] === '2020'; result[2] === '12'; result[3] === '02';
使用解構賦值的例子:
let regx = /^(?<one>.*):(?<two>.*)$/; let {groups: {one, two}} = regx.exec('foo:bar'); console.log(`one: ${one}, two: ${two}`);
當須要在正則表達式裏面引用命名捕獲組時,使用\k<name>
語法。
let duplicate = /^(?<half>.*).\k<half>$/; duplicate.test('a*b'); // false duplicate.test('a*a'); // true
若是引用一個不存在的命名捕獲組,會拋出異常:
命名捕獲組也能夠和普通數字捕獲組一塊兒使用:
let triplicate = /^(?<part>.*).\k<part>.\1$/; triplicate.test('a*a*a'); // true triplicate.test('a*a*b'); // false
命名捕獲組也能夠在String.prototype.replace
函數中引用,使用$<name>
語法。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; let result = "2020-12-02".replace(regx, '$<day>/$<month>/$<year>'); console.log(result === '02/12/2020');
String.prototype.replace
第2個參數能夠接受一個函數。這時,命名捕獲組的引用會做爲 groups
參數傳遞進取。
第2個參數的函數簽名是function (matched, capture1, ..., captureN, position, S, groups)
。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; let result = '2020-12-02'.replace(regx, (...args)=>{ let { day, month, year } = args[args.length - 1]; return `${day}/${month}/${year}` }); result === '02/12/2020';
若是一個可選的命名捕獲組沒有匹配時,在匹配結果中,此命名組依然存在,值是undefined
。
let regx = /^(?<optional>\d+)?$/; let matchers = regx.exec(''); matcher[0] === ''; matchers.groups.optional === undefined;
若是捕獲組不是可選的,匹配結果是null
。
let regx = /^(?<foo>\d+)$/; let matchers = regx.exec(''); matchers === null;
/(?<name>)/
和/\k<name>/
只有在命名捕獲組中才有意義。若是正則表達式沒有命名捕獲組,那麼/\k<name>/
僅僅是字符串字面量"k<name>"
而已。