一、匹配分組
字符 | 功能 |
| | 匹配左右任意一個表達式 |
(ab) | 將括號中的字符作為一個分組 |
\num | 引用分組num匹配到的字符串 |
(?<name>) | 分組起別名 |
(\k<name>) | 引用別名為name分組匹配到的字符串 |
1、|
需求:匹配出0-100之間的數字
分析:首先我們明確這之間的數字包含0,兩位數,100,也就是一位,兩位,三位的可能都有,鑒於一位0,三位100都是單獨數字,我們可以使用 | 來連接(相當於or),着重考慮一位數[1-9],兩位數[10-99],分析其特征,這里第一位數必須為[1-9],第二位[0-9]都可以(\d可以表示),對於一位數[1-9]的第二位可以不出現(?可以表示),再加個結尾$,防止234匹配到23的情況。因此正則表達式為:
/^[1-9]\d?$|0$|100$/
2、(ab) 將括號中的字符作為一個分組
需求 :在網頁開發或者爬蟲時,處理對象是HTML,比如某網頁HTML中有這樣的內容:<h1>我的CSDN</h1>。那么我該如何把<h1>content</h1>中的content提取出來呢?
分析:提取的內容用 () 括起來就可以了。<h1> </h1>是固定標簽,這是不變的,變的是content,因此我的正則表達式可表示為:
/<h1>(.*)<\/h1>/
let res = /<h1>(.*)<\/h1>/
'<h1>我的博客</h1>'.match(res) // (2) ["<h1>我的博客</h1>", "我的博客", index: 0, input: "<h1>我的博客</h1>", groups: undefined] // 0: "<h1>我的博客</h1>" // 1: "我的博客" // groups: undefined // index: 0 // input: "<h1>我的博客</h1>" // length: 2
我們看看兩個括號的情況:
let res = /<span>(\d+)<\/span><h1>(.*)<\/h1>/
'<span>1234</span><h1>我的CSDN</h1>'.match(res) // (3) ["<span>1234</span><h1>我的CSDN</h1>", "1234", "我的CSDN",
index: 0, input: "<span>1234</span><h1>我的CSDN</h1>", groups: undefined]
獲取元素為3個的數組,就不多展開了,根據數組內容就可以很方便的獲取到需要的content的內容。
所以說,() 在網頁開發或爬蟲里還是挺重要的。
3、\num 引用分組num匹配到的字符串
需求 :還是以網頁為例,比如判斷某網頁HTML格式是否正確,其中有內容:<html><h1>我的CSDN</h1></html>。這時,我們不關心里面的內容,我們關心的是格式是否正確,就是說這樣的格式:<html>標簽必須有</html>結束,<h1>標簽必須有</h1>結束。
分析:這個時候像html和h1才是關鍵內容,如果我們把這些用()保存起來,並且在后面一定對應這些內容,就能保證標簽的配對,而\num就是解決這樣的問題的。
首先我們看個錯誤的樣例:
let res = /<.+><.+>.+<\/.+><\/.+>/
'<html><h1>my csdn</h1></html>'.match(res) // ["<html><h1>my csdn</h1></html>", index: 0, input: "<html><h1>my csdn</h1></html>", groups: undefined]
let res = /<.+><.+>.+<\/.+><\/.+>/
'<html><h1>my csdn</h1></ht>'.match(res) // ["<html><h1>my csdn</h1></ht>", index: 0, input: "<html><h1>my csdn</h1></ht>", groups: undefined]
我們把/html改成了/ht 明顯格式不對,但還是匹配了。我們應該讓第一個<tag>的內容出現在最后</tag>中,因此需要保存起來,用()括起來
正確的方法:我們應該把<tag>用()括起來,變成<(tag)>,因此正則表達式為:
/<(.+)><(.+)>.+<\/\2><\/\1>/
let res = /<(.+)><(.+)>.+<\/\2><\/\1>/
'<html><h1>my csdn</h1></ht>'.match(res) // null
let res = /<(.+)><(.+)>.+<\/\2><\/\1>/
'<html><h1>my csdn</h1></html>'.match(res) // (3) ["<html><h1>my csdn</h1></html>", "html", "h1",
index: 0, input: "<html><h1>my csdn</h1></html>", groups: undefined]
解釋下,這個\2 和 \1。這個就是對應(tag)的分組,可以通過下面的index內容獲取。上面正確的標簽,那么 \1指的就是html,\2 指的就是h1
4、(?<name>) 分組起別名 和 (\k<name>) 引用別名
需求 :上面我們已經可以通過\num取得對應的內容用以限定前面的內容,但是如果我有100個括號,那我們就只能數括號的索引index,然后把用\index取得么?答案:當然不是。
分析:這時候取別名(?<name>)就派上用場了,它通過對括號里的內容取別名,然后通過(\k<name>)就可以取得對應的內容,你只要記住別名name,這樣就不用去數括號,記索引了。是不是很人性化......
這個語法是:在括號里面同時寫上取的別名,以 ?<name> 命名;引用時以 \k<name> 取得別名,所以該正則表達式為:
/<(?<key1>.+)><(?<key2>.+)>.+<\/(\k<key2>)><\/(\k<key1>)>/
let res1 = /<(?<key1>.+)><(?<key2>.+)>.+<\/(\k<key2>)><\/(\k<key1>)>/
'<html><h1>my csdn</h1></html>'.match(res1) // (5) ["<html><h1>my csdn</h1></html>", "html", "h1", "h1", "html",
index: 0, input: "<html><h1>my csdn</h1></html>", groups: {…}]
0: "<html><h1>my csdn</h1></html>"
1: "html"
2: "h1"
3: "h1"
4: "html" groups: key1: "html" key2: "h1" index: 0 input: "<html><h1>my csdn</h1></html>" length: 5 __proto__: Array(0)
關於正則分組別名,詳細的可以看之前總結的這篇博客:JavaScript 正則命名分組