前言
本文介紹一些正則中的常用名詞以及對應概念,譬如字元組,捕獲組、非捕獲組、反向引用、轉義和s
等
大綱
- 字元組
- 捕獲組
- 反向引用
- 非捕獲組
-
.
、s
和S
-
轉義
字元組
[]
字元組表示在同一個位置可能出現的各種字元,也就是說它的匹配結果只能是一個字元,不能是多個
例如[hello]
匹配的不是hello
而是h或e或l或o
特點
- 結果只會匹配一個字元
-
內部特殊字元無需轉義
[
]
除外- 另外,
^
出現在最開始位置時需要轉義 -
-
前後構成區間範圍時需要轉義(推薦永遠使用轉義-
)
- 另外,
-
-
表示連字元 -
^
表示排除符
示例
特殊字元無需轉義
[^*-+|(a)]
這個示例的含義是,匹配以下字元中的任意一個
-
^
*
-
+
|
(
a
)
- 可以看到,這些特殊字元在字元組中僅僅就是字元本身
連字元的作用
[z-a]
匹配這個正規表示式會報錯(Range out of order in character class
)
原因是連字元後面的字元碼要大於等於前面的字元碼
var str = `abc-`;
var reg = /[a-z-]/g;
// 最後的連字元沒有構成區間,所以僅僅表示 - 這個字元
str.match(reg); // ["a", "b", "c", "-"]
var str = "aAbc-";
var reg = /[A-a-z]/g;
// 通用,A-a 構成一個區間 之後的 -z 無法構成區間,於是它只能作為-字元本身
str.match(reg); // ["a", "A", "-"]
排除型
var str = `01ABabc-`;
var reg = /[^a-z]/g;
// 匹配了除a-z範圍外的任意字元
str.match(reg); // ["0", "1", "A", "B", "-"]
排除型字元組用法和普通的一樣,但是唯一區別是
- 排除型代表符合條件的都不匹配(功能相反)
特殊情況
var str = `abd,cdef`;
var reg = /[]/g;
var reg2 = /c/g;
var reg3 = /[]c/g;
str.match(reg); // [""] 匹配本身
str.match(reg2); // ["c"] 即匹配,號後面的c
str.match(reg3); // null 因為後面沒有c
-
在字元組以外表示單詞邊界
- 在字元組內,表示退格符(
)
捕獲組
捕獲組就是把正規表示式中子表示式匹配的內容,儲存到記憶體中以數字編號或顯式命名的組裡,方便後面引用
例如: /(a)(b)(c)/
中的捕獲組編號為
- 組
0
:abc
- 組
1
:a
- 組
2
:b
- 組
3
:c
其中,組0
是正規表示式整體匹配結果,組1
`2`3
才是子表示式匹配結果
特點
- 子表示式捕獲組編號從
1
開始,順序從左到右(例如編號1
是左側第一個()
包裹的子表示式的結果) - 可以在正規表示式中對前面捕獲的內容進行引用(反向引用)
- 也可以在程式中,對捕獲組捕獲的內容進行引用(比如
replace
中)
示例
子表示式捕獲組編號從1開始,順序從左到右
var str = "2017-07-29";
var reg = /(d{4})-(d{2})-(d{2})/;
// 非全域性模式有捕獲組結果
str.match(reg); // ["2017-07-29", "2017", "07", "29", index: 0, input: "2017-07-29"]
上述匹配中,除了整個正規表示式的結果外,還有各個捕獲組的結果,其中,子表示式的捕獲組從編號1
開始,如下
編號 | 捕獲組 | 匹配內容 |
---|---|---|
0 | (d{4})-(d{2})-(d{2}) | 2017-07-29 |
1 | d{4} | 2017 |
2 | d{2} | 07 |
3 | d{2} | 29 |
JS程式內的引用
- 在
replace
中,JS
通過$number
引用捕獲組內容 - 在外部匹配引用,
JS
通過RegExp.$number
引用捕獲組內容
var str = `<div id="code1" class="highlight"></div>`;
var reg = /<(w+)[^>]*>/g;
// <div></div>
str = str.replace(reg, "<$1>");
可以看到,在去除div
中的屬性時,先是整個匹配<divxxx>
,然後再把整個內容替換成<$1>
,其中$1
就是第一個捕獲組結果div
的引用
注,請不要引用$0
,因為它不屬於子表示式的捕獲組,在replace
中引用$0
沒有任何效果
var str = `abcd0123ABCD`;
var reg = /([a-z]+)(d+)([A-Z]+)/g;
reg.test(str); // true
console.log(RegExp.$0); // undefined
console.log(RegExp.$1); // abcd
console.log(RegExp.$2); // 0123
console.log(RegExp.$3); // ABCD
注,同樣$0
的引用沒有內容
反向引用
在正規表示式內部對捕獲組進行引用稱之為反向引用
var str = "boom==boom";
var reg = /(boom)==1/;
str.match(reg); // ["boom==boom", "boom", index: 0, input: "boom==boom"]
可以看到,正則中1
的值就是捕獲組1
匹配到的結果boom
因此,這個表示式等價於(boom)==boom
示例
var str = `1234567899`;
var str2 = `12345678999`;
var reg = /^(?:([0-9])(?!1{2})){1,}$/;
reg.test(str); // true
reg.test(str2); // false
上例中的效果是,匹配一個數字,但是數字中不允許連續出現3
次以上的重複數字
- 用到反向引用可以很好的實現
非捕獲組
上述可以看到()
包括的內容預設匹配時都在捕獲組中
但是有時候,因為特殊原因用到了()
,但又沒有引用它的必要,這時候就可以用非捕獲組宣告,防止它作為捕獲組,降低記憶體浪費
-
?:
可以宣告一個子表示式為非捕獲組
var str = `abcd0123ABCD`;
var reg = /(?:[a-z]+)(d+)([A-Z]+)/g;
reg.test(str); // true
console.log(RegExp.$0); // undefined
console.log(RegExp.$1); // 0123
console.log(RegExp.$2); // ABCD
可以看到,(?:[a-z]+)
將這個子表示式宣告成了非捕獲組,因此捕獲組的編號直接跳過了它,從下一個(d+)
開始
.
、s
和S
首先說下.
- 定義是除
以外的任何字元
- 但是,在一些
Chrome
、Firefox
等核心中,代表
和
以外的字元
- 如果要匹配
.
本身,請用.
再說說s
與S
-
s
是匹配所有的空白字元,包括空白
、換行
、tab縮排
等所有空白 -
S
是指除了空白以外的任何字元(和.
區別下,.
裡面還多了一部分空白)
那如何匹配所有字元呢?
-
(.|
或者是
)[sS]
(推薦用法) - 請不要試圖使用
[.
或
][.
,這種寫法只表示小數點或
]
字元中的一個
示例
請寫一個表示式,去除多行註釋
var str = `
var a = 1;
/**
* 這裡是註釋
*/
var b = 2;
console.log(a)`;
var reg = xxx;
str = str.replace(reg, ``);
解答
var reg = //*{1,}[sS]**//g;
這裡就用的了用[sS]
來匹配所有的字元(因為僅僅是.
是無法匹配
的)
單詞邊界
匹配單詞邊界,不匹配任何字元
簡單的說,匹配的位置,一側是構成單詞的字元,另一側是非單詞字元,字串的開始或結束
而其中單詞的判斷就是w
的匹配範圍(正常a-zA-Z0-9_
,JS
舉例)
注,有一特例,在字元組中[]
表示的是退格符
特點
- 零寬,即匹配的是位置而不是字元
- 以
w
來界定單詞 - 字元組中是退格符的意思
示例
var str = `abc_d=efg+hij哈opq%`;
var reg = /../g;
// ["d=", "g+", "j哈", "q%"]
str.match(reg);
可以看到,分別在如下幾處有單詞分界
-
d
和=
直接有一個分界 -
g
和+
之間 -
j
和哈
-
q
和%
轉義
var str = `ab\cd`; // 字串 abcd
var str2 = `ab\\cd`; // 字串 ab\cd
var reg = /ab\\cd/;
var reg2 = new RegExp(`ab\\cd`);
reg.test(str); // false
reg.test(str2); // true
reg2.test(str); // true
reg2.test(str2); // false
出現的地方,得多加註意,需要梳理清楚轉義邏輯,通過上例可以看到,在正則中出現的
和在字串中出現的
意義不一樣
-
reg
中,出現在正則中,所以
\\
的意思就是匹配\
字串,所以測試str2
通過,str
失敗 -
reg2
中,出現在字串中,所以
\\
的意思\
,然後構建為正規表示式,最終在正則中是\
,也就是匹配字串本身,所以測試
str
通過,str2
失敗
附錄
部落格
初次釋出2017.07.31
於個人部落格
http://www.dailichun.com/2017/08/01/regularExpressionConcepts.html