JavaScript 正則命名分組【推薦】
前言
以往我們只是習(xí)慣于通過數(shù)組下標(biāo)來訪問正則匹配到的分組,但分組達(dá)到4、5個時,標(biāo)識起來就會非常麻煩。V8早已實(shí)現(xiàn)了正則命名分組提案,只是我們很少使用,本文將介紹JS的正則命名分組。
以往的做法
假設(shè)要使用正則匹配一個日期的年月日,以往我們會這樣做:
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
這里有幾個缺點(diǎn):
- 要找到一個分組的位置,你必須要去數(shù)括號的位置,有時嵌套起來會更令人頭疼。
- 后面維護(hù)代碼的同學(xué)閱讀起來,還要根據(jù)下標(biāo)找到正則里面對應(yīng)的括號,并且要再次閱讀括號里面的正則才知道含義。
- 當(dāng)你調(diào)整正則捕獲分組的數(shù)量、順序或嵌套時,你必要還要對下面的代碼做調(diào)整。
所有這些問題,都可以通過正則命名分組來解決。
現(xiàn)在的玩法
現(xiàn)在你只需要給分組里面一個命名標(biāo)識即可:
(?<year>\d{4})
這里,我們用變量year標(biāo)記了上一個捕獲組#1。 該名稱必須是合法的JavaScript標(biāo)識符。 匹配后,您可以通過matchObj.groups.year訪問捕獲的字符串。
讓我們通過命名分組重寫前面的代碼:
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é)果會多了一個groups 的屬性,這個屬性中包含了一切命名分組的捕獲結(jié)果。配合上解構(gòu)大法使用又是一股清流:
const {groups: {day, year}} = RE_DATE.exec('1999-12-31'); console.log(year); // 1999 console.log(day); // 31
當(dāng)然,即使你使用了命名分組,那么返回的結(jié)果還可以通過以往的數(shù)組下標(biāo)方式訪問:
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)槟梢灾苯涌吹矫總€組的用途。
反向引用
反向引用命名分組\k<name>
看下面這個匹配重復(fù)單詞的例子:
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/; RE_TWICE.test('abc!abc'); // true RE_TWICE.test('abc!ab'); // false
同時也可以使用以往的反向引用方式:
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形參密密麻麻看得心慌慌,很多都用不上,那么我們看看更簡單的寫法:
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直取最后一個參數(shù),再接上一個解構(gòu)大法,結(jié)果又是一股清流。
命名分組沒有匹配結(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
反向引用一個不存在的分組名:
/\k<foo>/u // SyntaxError: Invalid named capture referenced /\k<foo>/.test("k<foo>") // true, 非 Unicode 下為了向后兼容,k 前面的 \ 會被丟棄
在 reaplce() 方法的替換字符串中引用一個不存在的分組:
"abc".replace(/(?<foo>.*)/, "$<bar>") // SyntaxError: Invalid replacement string "abc".replace(/(.*)/, "$<bar>") // "$<bar>",不包含命名分組時會向后兼容
最后
- Chrome60 已支持命名分組
- 通過babel插件處理兼容問題
babel-plugin-transform-modern-regexp
總結(jié)
以上所述是小編給大家介紹的JavaScript 正則命名分組,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
IScroll5實(shí)現(xiàn)下拉刷新上拉加載的功能實(shí)例
本篇文章主要介紹了IScroll5實(shí)現(xiàn)下拉刷新上拉加載的功能實(shí)例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08xml分頁+ajax請求數(shù)據(jù)源+dom取結(jié)果實(shí)例代碼
最近做的一個項(xiàng)目里的某個小功能,主要是為了方便選擇數(shù)據(jù) 演示地址:由于有惡意程序,所以去掉地址2008-10-10JavaScript Accessor實(shí)現(xiàn)說明
關(guān)于Getter與Setter大家一定不會陌生,下面簡單介紹幾種我所知道的在JavaScript中實(shí)現(xiàn)G/S的方法.2010-12-12JS獲取select-option-text_value的方法
這篇文章主要介紹了JS獲取select-option-text_value的方法,有需要的朋友可以參考一下2013-12-12一個JS函數(shù)搞定網(wǎng)頁標(biāo)題(title)閃動效果
這篇文章主要介紹了使用JS函數(shù)實(shí)現(xiàn)網(wǎng)頁標(biāo)題(title)閃動效果的代碼,需要的朋友可以參考下2014-05-05Express實(shí)現(xiàn)前端后端通信上傳圖片之存儲數(shù)據(jù)庫(mysql)傻瓜式教程(二)
這篇文章主要介紹了Express實(shí)現(xiàn)前端后端通信上傳圖片之存儲數(shù)據(jù)庫(mysql)傻瓜教程(二)的相關(guān)資料,需要的朋友可以參考下2015-12-12javascript中導(dǎo)出與導(dǎo)入實(shí)現(xiàn)模塊化管理教程
這篇文章主要給大家介紹了關(guān)于javascript中導(dǎo)出與導(dǎo)入實(shí)現(xiàn)模塊化管理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12