【正則】964- 正則表達(dá)式的括號(hào)如何使用?

最近再一次重溫老姚大佬的《JavaScript 正則表達(dá)式迷你書》 , 并將核心知識(shí)點(diǎn)整理一遍,方便復(fù)習(xí)。
原書寫得非常棒,建議看下原書啦。 地址:https://github.com/qdlaoyao/js-regex-mini-book
回復(fù)“8”加入面試題分享群
簡單理解:括號(hào)提供了分組,便于我們使用它。
通常有兩種引用情況:在JS代碼中引入,和在正則表達(dá)式中引入。
分組和分支結(jié)構(gòu),主要是強(qiáng)調(diào)括號(hào)內(nèi)是一個(gè)整體,即提供子表達(dá)式。
分組如 /(ab)+/g匹配連續(xù)出現(xiàn)的ab。分支結(jié)構(gòu)如 /(a|b)+/g匹配出現(xiàn)的a或b表達(dá)式。
1.分組引用
如在日期匹配的時(shí)候,就可以這么改造:
// 原來
let r = /\d{4}-\d{2}-\d{2}/;
// 現(xiàn)在
let r = /(\d{4})-(\d{2})-(\d{2})/;
提取數(shù)據(jù)
"2019-03-14".match(r);
r.exec("2019-03-14");
// ["2019-03-14", "2019", "03", "14", index: 0, input: "2019-03-14"]
RegExp.$1; // "2019"
RegExp.$2; // "03"
RegExp.$3; // "14"
替換
將 yyyy-mm-dd 轉(zhuǎn)成 mm/dd/yyyy。
"2019-03-14".replace(r, "$2/$3/$1");
// 等價(jià)于
"2019-03-14".replace(r, function(){
return RegExp.$2 + '/' + RegExp.$3 + '/' + RegExp.$1;
});
2. 反向引用
使用 \n 表示第 n 個(gè)分組,比如 \1 表示第 1 個(gè)分組:
let r = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
r.test("2019-03-15");
r.test("2019/03/15");
r.test("2019.03.15");
r.test("2019-03/15");
多個(gè)括號(hào)嵌套
按照開括號(hào)的順序:
let r = /^((\d)(\d(\d)))\1\2\3\4$/;
let s = "1231231233";
r.test(s);
console.log([RegExp.$1,RegExp.$2,RegExp.$3,RegExp.$4]);
// ["123", "1", "23", "3"]
特殊情況
\10 表示的是第 10 個(gè)分組,若要匹配 \ 和 0 時(shí),使用 (?:\1)0 或 \1(?:0)。
let r = /(1)(2)(3)(4)(5)(6)(7)(8)(9)(#) \10+/;
let s = "123456789# #####";
r.test(s); // true
當(dāng)引用不存在的分組
如匹配 \2 是前面不存在,則匹配 \2 本身,即對(duì) 2 的轉(zhuǎn)義,不同瀏覽器可能不同:
let r = /\1\2\3\4/;
r.test("\1\2\3\4"); // true
"\1\2\3\4".split('');// ["", "", "", ""]
分組后面有量詞
當(dāng)分組后面有量詞的話,則捕獲的是最后一次的匹配:
"12345".match(/(\d)+/); // ["12345", "5", index: 0, input: "12345"]
/(\d)+ \1/.test("12345 1"); // false
/(\d)+ \1/.test("12345 5"); // true
3. 向后引用
\n 表示后向引用, \1 是指在正則表達(dá)式中,從左往右數(shù)第1個(gè) () 中的內(nèi)容;以此類推, \2 表示第2個(gè) (), \0 表示整個(gè)表達(dá)式。
let rgx = /\d{4}(\-|\/|.)\d{1,2}\1\d{1,2}/
rgx.test("2020-01-05") // true
rgx.test("2020-01.05") // false
上面案例中,\1代表重復(fù) (\-|\/|.) 。
4. 相關(guān)案例
這里只寫出核心代碼。
模擬字符串 trim方法
// 1 匹配首尾空白符,替換成空字符
" aaa ".replace(/^\s+|\s+$/g, ""); // "aaa"
// 2 匹配整個(gè)字符串,再用引用提取對(duì)應(yīng)數(shù)據(jù)
" aaa ".replace(/^\s*(.*?)\s*$/g, "$1");// "aaa"
每個(gè)單詞首字母大寫
"hi leo hi boy!".toLowerCase().replace(
/(?:^|\s)\w/g,
c => c.toUpperCase()
);
// "Hi Leo Hi Boy!"
駝峰化 和 中劃線化
"-leo-and-pingan".replace(/[-_\s]+(.)?/g,
(match, c) => c ? c.toUpperCase() : ''
);
// "LeoAndPingan"
"LeoAndPingan".replace(/([A-Z])/g, "-$1").replace(
/[-_\s]+g/,"-"
).toLowerCase();
// "-leo-and-pingan"
匹配成對(duì)HTML標(biāo)簽
匹配成對(duì)標(biāo)簽 <h1>leo<\h1>,而不匹配不成對(duì)標(biāo)簽 <h1>leo<\h2>。
let r = /<([^>]+)>[\d\D]*<\/\1>/;
r.test("<h1>leo leo leo</h1>"); // true
r.test("<a>leo leo leo</a>"); // true
r.test("<h1>leo leo leo</h2>"); // false

回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~
點(diǎn)擊“閱讀原文”查看 120+ 篇原創(chuàng)文章
