公司的小伙伴希望能講一下正則表達式,于是趁著這個機會自己也把正則表達式的重新學習了一下,由于不同語言對正則表達式提供了不同的方法支持,以下所有的正則測試均基于Javascript
1. 元字符
正則表達式中的字符可以認為有兩類,一類被稱為元字符,代表的是有在正則表達式中有特殊含義的字符,另一類就是普通字符。
個人認為元字符分為了三類:固有語義,簡寫字符集和分組匹配
1.1 固有語義的字符
1.1.1 選擇字符
選擇字符有兩種[]
和[^]
,[]
表示匹配結果包含[]
中的任意字符,[^]
則表示匹配結果不能包含[^]
中的字符
/[1234]/.test('1'); // true
/[1234]/.test('5'); // false
/[^1234]/.test('2'); // false
/[^1234]/.test('5'); // true
需要注意的是[]
和[^]
中的字符,除開部分特殊字符外(例如:[
,]
,-
等),都是自帶轉義屬性。也就是說[]
中的字符都不再具有特殊意義
// 在正則中‘.’是任意匹配的意思,但是[]中失去了其本來的意義
/./.test(1); // true
/[.]/.test(1); // false
/[.]/.test('.'); // true
1.1.2 重復字符
表示一個字符出現次數包括:?
, *
, +
, {m, n}
// 0次或1次匹配
/[a]?/.test('a'); // true
/[a]?/.test('b'); // true
// 0次或多次匹配
/[a]*/.test('a'); // true
/[a]*/.test('b'); // true
// 1次或多次匹配
/[a]+/.test('a'); // true
/[a]+/.test('b'); // false
// 出現m到n次
/[a]{2,3}/.test('aab'); // true
/[a]{2,3}/.test('abab'); // false
1.1.3 錨點字符
有表示開始的^
和表示結束的$
,用于限制正則匹配的開始和結束
/[1]/.test('12'); // true
// 以1開頭
/^[1]/.test('21'); // false
/^[1]/.test('12'); // true
// 以1結尾
/[1]$/.test('12'); // false
/[1]$/.test('21'); // true
1.1.4 轉義字符
使用\
來進行將一些元字符進行轉義,從而使得元字符可以進行匹配
/[]/.test('[]'); // false
/\[\]/.test('[]'); // true
1.1.5 通配字符
使用.
來匹配任意字符,只要匹配字符串不為空匹配結果都為真
/./.test('a-1sd'); // true
1.1.6 或字符
使用|
來對多個字符取并集匹配
/1|2/.test('1'); // true, 等價于/[12]/.test('1')
/1|2/.test('2'); // true, 等價于/[12]/.test('1')
/The|to/.test('to'); // true
1.1.7 非貪婪匹配
在重復字符后面使用?
來進行非貪婪匹配,非貪婪匹配是指在匹配字符對時候盡可能少的匹配
// 使用replace函數來驗證
'aaab'.replace(/[a]+/g, '='); // =b
'aaab'.replace(/[a]+?/g, '='); // ===b
上面的例子中:
第一個使用了貪婪模式,因此\[a]+\
將匹配aaa
,因此執行替換的時候將aaa
替換為了=
第二個使用了非貪婪匹配,因此\[a]+?\
將分別匹配每個a
,因此最后將每個a
分別替換為=
,aaa
就變為===
1.2 簡寫字符集
將一些字符,和轉義符號配合使用,可以得到一些正則表達式默認匹配范圍
1.2.1 字符數字匹配集
使用\w
可以匹配字符數字,相當于[a-zA-Z0-9_]
,而\W
匹配所有非字符數字,相當于[^a-zA-Z0-9_]
/\w/.test('1'); // true
/\W/.test('1'); // false
1.2.2 數字匹配集
使用\d
匹配數字,相當于[0-9]
,同樣\D
匹配非數字,相當于[^0-9]
/\d/.test('1'); // true
/\D/.test('1'); // false
1.2.3 空格匹配集
使用\s
匹配空格,相當于[ ]
,使用\S
匹配非空格,相當于[^ ]
/\s/.test(' '); // true
/\S/.test(' '); // false
1.2.4 其他
其他還包括換行符匹配\n
,回車匹配\r
,制表符匹配\t
等
1.3 分組
正則表達式中可以將匹配進行分組,并可以分別獲取匹配的分組,同時表達式中也可以指定分組的引用
1.3.1 分組匹配
使用()
可以將正則表達式進行分組
/(The)|(To)/.test('The'); // true
看上去和之前的差不多,但是,這里可以在正則表達式中,利用捕獲模式(/ + 數字
)和替換模式($ + 數字
)獲取,獲得對應分組的引用,分組的計數是從1開始的
// 捕獲模式
/(The)(To)\1/.test('TheTo'); // false
/(The)(To)\1/.test('TheToThe'); // true
/(The|To)\1/.test('TheThe'); // true
/(The|To)\1/.test('ToTo'); // true
/(The|To)\1/.test('TheTo'); // false
// 替換模式
'TheTo'.replace(/(The)(To)/, '$2$1') // ToThe
1.3.2 非獲取匹配
在分組匹配中,可以使用(?)
的方式,來進行匹配,但是匹配后不進行存儲使用,也就是不能使用捕獲模式和替換模式的方式獲取到分組信息
1.3.2.1 匹配不獲取
使用(?:)
去匹配字符,通常和|
來組合使用
/Test(?:er|or)/.test('Tester'); // true
/Test(?:er|or)/.test('Testor'); // true
/Test(er|or)\1/.test('Testerer'); // true
/Test(er|or)\1/.test('Testoror'); // true
/Test(?:er|or)\1/.test('Testeror'); // false
/Test(?:er|or)\1/.test('Tester\1'); // true
1.3.2.2 正向預查匹配
使用(?=)
來進行正向匹配,匹配字符串開始處進行查找
/Windows(?=2000|3000)/.test('Windows3000'); // true
/Windows(?=2000|3000)/.test('Windows4000'); // false
1.3.2.3 正向預查不匹配
使用(?!)
來進行匹配和(?=)
剛好相反
/Windows(?!2000|3000)/.test('Windows3000'); // false
/Windows(?!2000|3000)/.test('Windows4000'); // true
1.3.2.4 反向預查匹配
使用(?<=)
來進行匹配
/(?<=2000|3000)Windows/.test('3000Windows'); // true
/(?<=2000|3000)Windows/.test('4000Windows'); // false
1.3.2.4 反向預查不匹配
使用(?<!)
來進行匹配,和(?<=)
相反
/(?<!2000|3000)Windows/.test('3000Windows'); // false
/(?<!2000|3000)Windows/.test('4000Windows'); // true
2. 匹配模式
常用的匹配模式有三個:i
, g
, m
,不同的語言支持的匹配模式的會有所不同
2.1 忽略大小匹配
使用i
做為匹配模式,可以忽略匹配中的大小寫
/[A]/.test('a'); // false
/[A]/i.test('a'); // true
2.2 全局匹配
使用g
做為匹配模式,可以匹配字符串中的所有字符,而不是第一個字符
'abcabcabc'.replace(/[a]/, '='); // =bcabcabc
'abcabcabc'.replace(/[a]/g, '='); // =bc=bc=bc
2.2 多行匹配
使用m
做為匹配模式,可以匹配多行字符,通常和g
一起使用
3. Javascript支持正則的方法
3.1 支持的方法
各語言都提供了各種支持正則都方法,Javascript以下方法都支持正則表達式的使用:
RegExp.prototype.exec()
RegExp.prototype.test()
String.prototype.replace()
3.2 lastIndex
Javascript中,在正則表達式對象存在lastIndex
屬性,每進行一次匹配,這個屬性會進行更新為當前匹配位置,并以在下一次匹配時,以這個位置開始進行匹配
let str = 'abc';
let reg = /[a]/g;
reg.test(str); // true
console.log(reg.lastIndex); // 1
reg.test(str); // false
// 由于匹配失敗,所以會被重置為0
console.log(reg.lastIndex); // 0
4. 總結
正則表達式的識別主要是區別元符號和普通符號的,同時注意轉義符號的使用特點,讀懂正則表達式就不難了。