正則表達式

正則表達式.png

公司的小伙伴希望能講一下正則表達式,于是趁著這個機會自己也把正則表達式的重新學習了一下,由于不同語言對正則表達式提供了不同的方法支持,以下所有的正則測試均基于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. 總結

正則表達式的識別主要是區別元符號和普通符號的,同時注意轉義符號的使用特點,讀懂正則表達式就不難了。

5. 參考

你應該學習正則表達式
Learn-regex-easy-way
百度百科-正則表達式
MDN-RegExp

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容