JavaScript 正則命名分組【推薦】
前言
以往我們只是習(xí)慣于通過(guò)數(shù)組下標(biāo)來(lái)訪問(wèn)正則匹配到的分組,但分組達(dá)到4、5個(gè)時(shí),標(biāo)識(shí)起來(lái)就會(huì)非常麻煩。V8早已實(shí)現(xiàn)了正則命名分組提案,只是我們很少使用,本文將介紹JS的正則命名分組。
以往的做法
假設(shè)要使用正則匹配一個(gè)日期的年月日,以往我們會(huì)這樣做:
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31
這里有幾個(gè)缺點(diǎn):
- 要找到一個(gè)分組的位置,你必須要去數(shù)括號(hào)的位置,有時(shí)嵌套起來(lái)會(huì)更令人頭疼。
- 后面維護(hù)代碼的同學(xué)閱讀起來(lái),還要根據(jù)下標(biāo)找到正則里面對(duì)應(yīng)的括號(hào),并且要再次閱讀括號(hào)里面的正則才知道含義。
- 當(dāng)你調(diào)整正則捕獲分組的數(shù)量、順序或嵌套時(shí),你必要還要對(duì)下面的代碼做調(diào)整。
所有這些問(wèn)題,都可以通過(guò)正則命名分組來(lái)解決。
現(xiàn)在的玩法
現(xiàn)在你只需要給分組里面一個(gè)命名標(biāo)識(shí)即可:
(?<year>\d{4})
這里,我們用變量year標(biāo)記了上一個(gè)捕獲組#1。 該名稱必須是合法的JavaScript標(biāo)識(shí)符。 匹配后,您可以通過(guò)matchObj.groups.year訪問(wèn)捕獲的字符串。
讓我們通過(guò)命名分組重寫前面的代碼:
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31
如果正則里面有了命名分組,那么匹配結(jié)果會(huì)多了一個(gè)groups 的屬性,這個(gè)屬性中包含了一切命名分組的捕獲結(jié)果。配合上解構(gòu)大法使用又是一股清流:
const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
console.log(year); // 1999
console.log(day); // 31
當(dāng)然,即使你使用了命名分組,那么返回的結(jié)果還可以通過(guò)以往的數(shù)組下標(biāo)方式訪問(wèn):
const year2 = matchObj[1]; // 1999 const month2 = matchObj[2]; // 12 const day2 = matchObj[3]; // 31
命名分組具有以下優(yōu)點(diǎn):
- 找到分組的“ID”更容易。
- 匹配的代碼變得自描述性,因?yàn)榉纸M的ID描述了捕獲的內(nèi)容。
- 如果更改分組的順序,則不必更改匹配的代碼。
- 分組的名稱也使正則表達(dá)式更易于理解,因?yàn)槟梢灾苯涌吹矫總€(gè)組的用途。
反向引用
反向引用命名分組\k<name>
看下面這個(gè)匹配重復(fù)單詞的例子:
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc'); // true
RE_TWICE.test('abc!ab'); // false
同時(shí)也可以使用以往的反向引用方式:
const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
RE_TWICE.test('abc!abc'); // true
RE_TWICE.test('abc!ab'); // false
replace( )
字符串方法replace()以兩種方式支持命名分組:
方式一
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log('1999-12-31'.replace(RE_DATE,
'$<month>/$<day>/$<year>'));
// 12/31/1999
如果replace不一定是直接返回新的拼接字符串,那么可以看看下面的辦法:
方式二
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log('1999-12-31'.replace(
RE_DATE,
(g, y, m, d, offset, input, {year, month, day}) =>
month+'/'+day+'/'+year));
// 12/31/1999
看看這replace的callback形參密密麻麻看得心慌慌,很多都用不上,那么我們看看更簡(jiǎn)單的寫法:
console.log('1999-12-31'.replace(RE_DATE,
(...args) => {
const {year, month, day} = args.slice(-1)[0];
return month+'/'+day+'/'+year;
}));
// 12/31/1999
這里配合上spread operator直取最后一個(gè)參數(shù),再接上一個(gè)解構(gòu)大法,結(jié)果又是一股清流。
命名分組沒(méi)有匹配結(jié)果?
如果可選的命名組不被匹配,則其屬性值被設(shè)置為undefined,但key是仍存在:
const RE_OPT_A = /^(?<as>a+)?$/;
const matchObj = RE_OPT_A.exec('');
// We have a match:
console.log(matchObj[0] === ''); // true
// Group <as> didn't match anything:
console.log(matchObj.groups.as === undefined); // true
// But property as exists:
console.log('as' in matchObj.groups); // true
異常情況
分組名不能有重復(fù)項(xiàng):
/(?<foo>a)(?<foo>b)/ // SyntaxError: Duplicate capture group name
反向引用一個(gè)不存在的分組名:
/\k<foo>/u // SyntaxError: Invalid named capture referenced
/\k<foo>/.test("k<foo>") // true, 非 Unicode 下為了向后兼容,k 前面的 \ 會(huì)被丟棄
在 reaplce() 方法的替換字符串中引用一個(gè)不存在的分組:
"abc".replace(/(?<foo>.*)/, "$<bar>") // SyntaxError: Invalid replacement string "abc".replace(/(.*)/, "$<bar>") // "$<bar>",不包含命名分組時(shí)會(huì)向后兼容
最后
- Chrome60 已支持命名分組
- 通過(guò)babel插件處理兼容問(wèn)題
babel-plugin-transform-modern-regexp
總結(jié)
以上所述是小編給大家介紹的JavaScript 正則命名分組,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
layui監(jiān)聽(tīng)工具欄的實(shí)例(操作列表按鈕)
今天小編就為大家分享一篇layui監(jiān)聽(tīng)工具欄的實(shí)例(操作列表按鈕),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解
正則的思想都是一樣的,但是具體的寫法會(huì)有所不同,下面這篇文章主要給大家介紹了關(guān)于JavaScript正則表達(dá)式中g(shù)標(biāo)志的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
JavaScript之面向?qū)ο骭動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
JavaScript的面向?qū)ο缶幊毯痛蠖鄶?shù)其他語(yǔ)言如Java、C#的面向?qū)ο缶幊潭疾惶粯?。下面通過(guò)本文給大家介紹js面向?qū)ο笾R(shí),包括面向?qū)ο蟮膬蓚€(gè)基本概念,一起看看吧2017-06-06
javascript offsetX與layerX區(qū)別
FF沒(méi)有offsetX屬性,有個(gè)layerX屬性,只要將事件源的位置設(shè)置成相對(duì)定位(position:relative)或絕對(duì)定位(position:absolute),兩者結(jié)果就相等,表示事件源相對(duì)于父元素的X坐標(biāo)。2010-03-03
javascript利用canvas實(shí)現(xiàn)鼠標(biāo)拖拽功能
這篇文章主要為大家詳細(xì)介紹了javascript利用canvas實(shí)現(xiàn)鼠標(biāo)拖拽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
js中判斷數(shù)字\字母\中文的正則表達(dá)式 (實(shí)例)
js中判斷數(shù)字\字母\中文的正則表達(dá)式,需要的朋友可以參考下2012-06-06
JavaScript中Array實(shí)例方法filter的實(shí)現(xiàn)原理
filter() 方法創(chuàng)建一個(gè)新數(shù)組,其中包含通過(guò)所提供函數(shù)實(shí)現(xiàn)的測(cè)試的所有元素,本文將給大家介紹JavaScript中Array實(shí)例方法filter的實(shí)現(xiàn)原理,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-03-03
基于vue實(shí)現(xiàn)移動(dòng)端圓形旋鈕插件效果
最近公司有一個(gè)項(xiàng)目的需要做出旋鈕的效果,旋鈕有十個(gè)檔,根據(jù)手指旋轉(zhuǎn)切換,旋轉(zhuǎn)時(shí)接近最近的檔會(huì)有吸附效果。這篇文章主要介紹了vue實(shí)現(xiàn)移動(dòng)端圓形旋鈕插件效果 ,需要的朋友可以參考下2018-11-11

