全方面系統認識JavaScript正則表示式
一、正則表示式簡介
1、什麼是正則表示式
正則表示式,又稱規則表示式。(英語:Regular Expression,在程式碼中常簡寫為regex、regexp或RE),電腦科學的一個概念。正則表示式通常被用來檢索、替換那些符合某個模式(規則)的文字。
簡單的說,就是按照某種規則去匹配符合條件的字串。
2、視覺化正則表示式工具
Regexper:https://regexper.com/
二、RegExp物件
例項化
RegExp
的兩種方式。
兩種方式定義RegExp物件。
1、字面量
let reg = /[a-z]{3}/gmi; let reg = /[a-z]{3}/g; let reg = /[a-z]{3}/m; let reg = /[a-z]{3}/i;
標誌
g
global 代表全域性搜尋。如果不新增,搜尋到第一個匹配停止。m
Multi-Line 代表多行搜尋。i
ignore case 代表大小寫不敏感,預設大小寫敏感。
2、建構函式
let reg = new RegExp('\\bis\\b', 'g');
因為JavaScript字串中\
屬於特殊字元,需要轉義。
三、元字元
把元字元當作轉義字元。
正則表示式有兩種基本字元型別組成。
- 原義文字字元
- 元字元
1、原義文字字元
表示原本意義上是什麼字元,就是什麼字元。
2、元字元
是在正則表示式中有特殊含義的非字母字元。
* + ? $ ^ . | \ ( ) { } [ ]
| 字元 | 含義 |
| :-: | :-- |
| \t
| 水平製表符 |
| \v
| 垂直製表符 |
| \n
| 換行符 |
| \r
| 回車符 |
| \0
| 空字元 |
| \f
| 換頁符 |
| \cX
| 控制字元,與X對應的控制字元(Ctrl + X) |
類似於轉義字元。
四、字元類
表示符合某種特性的字元類別。
使用元字元[]
可以構建一個簡單的類。
所謂類是指符合某些特性的物件,一個泛指,而不是某個字元。
例子
表示式[abc]
把字元a
或b
或c
歸為一類,表示式可以匹配這一類中的任意一個字元。
// replace() 方法用於在字串中用一些字元替換另一些字元,或替換一個與正則表示式匹配的子串。 'a1b2c3d4e5'.replace(/[abc]/g, '0'); //010203d4e5
字元類取反
我們想要替換不是abc
中任意一個字元的字元。
// 元字元 ^ 建立一個 反向類/負向類
'abcdefg'.replace(/[^abc]/g, '0'); //abc0000
五、範圍類
匹配這一個範圍內的字元。
如果我們想要匹配數字0-9
,那麼我們可能會這樣寫[0123456789]
。
如果我們想要匹配26
個字母,那麼我們可能會這樣寫[abcdefghijklmnopqrstuvwxyz]
。
這樣略顯麻煩,所以才會有範圍類。
例子
// 替換所有數字
'a1c2d3e4f5'.replace(/[0-9]/g, 'x'); //axcxdxexfx
// 替換所有小寫字母
'a1c2d3e4f5'.replace(/[a-z]/g, 'x'); //x1x2x3x4x5
// []組成的類內部是可以連寫的。替換所有大小寫字母
'a1C2d3E4f5G6'.replace(/[a-zA-Z]/g, '*'); //*1*2*3*4*5*6
疑問
如果我想替換數字,並且連帶-
符號也一起替換呢?
// 替換所有數字和橫槓
'2018-5-21'.replace(/[0-9-]/g, '*'); //*********
六、預定義類
一些已經定義的類,可以直接使用。
| 字元 | 等價類 | 含義 |
| :-: | :-- | :-- |
| .
| [^\r\n]
| 除了回車、換行之外的所有字元 |
| \d
| [0-9]
| 數字字元 |
| \D
| [^0-9]
| 非數字字元 |
| \s
| [\t\n\x0B\r]
| 空白符 |
| \S
| [^\t\n\x0B\r]
| 非空白符 |
| \w
| [a-zA-Z_0-9]
| 單詞字元(字母、數字、下劃線) |
| \W
| [^a-zA-Z_0-9]
| 非單詞字元 |
例子
替換一個 ab
+ 數字
+ 任意字元
的字串
// 寫法1
'ab0c'.replace(/ab[0-9][^\r\n]/g, 'TangJinJian'); //TangJianJian
// 寫法2
'ab0c'.replace(/ab\d./g, 'TangJinJian'); //TangJianJian
七、單詞邊界
| 字元 | 含義 |
| :-: | :-- |
| ^
| 以xxx開始(不在中括號內時的含義) |
| $
| 以xxx結束 |
| \b
| 單詞邊界 |
| \B
| 非單詞邊界 |
例子
我想替換的字串,屬於那種只在開頭出現的。
'YuYan is a boy, YuYan'.replace(/^YuYan/g, 'TangJinJian'); //TangJinJian is a boy, YuYan
我想替換的字串,屬於那種只在結尾出現的。
'YuYan is a boy, YuYan'.replace(/YuYan$/g, 'TangJinJian'); //YuYan is a boy, TangJinJian
單詞邊界例子。
// 替換所有is為0
'This is a man'.replace(/is/g, '0'); //Th0 0 a man
// 替換所有is前面帶有單詞邊界的字串
'This is a man'.replace(/\bis/g, '0'); //This 0 a man
// 替換所有is前面沒有單詞邊界的字串
'This is a man'.replace(/\Bis\b/g, '0'); //Th0 is a man
八、量詞
用來處理連續出現的字串。
| 字元 | 含義 |
| :-: | :-- |
| ?
| 出現零次或一次(最多出現一次) |
| +
| 出現一次或多次(至少出現一次) |
| *
| 出現零次或多次(任意次) |
| {n}
| 出現n次 |
| {n,m}
| 出現n到m次 |
| {n,}
| 至少出現n次 |
我想替換字串中連續出現10
次的數字為*
。
'1234567890abcd'.replace(/\d{10}/, '*'); //*abcd
我想替換字串中的QQ號碼。
'我的QQ是:10000'.replace(/[1-9][0-9]{4,}/, '12345678'); //我的QQ是:12345678
九、貪婪模式
儘可能多的匹配。
有這樣的一種場景下的正則表示式,/\d{3,6}/
該替換3個數字還是6個數字呢,4、5個數字?
// 貪婪模式會盡可能的往多的方面去匹配
'123456789'.replace(/\d{3,6}/, 'x'); //x789
'123456789'.replace(/\d+/, 'x'); //x
'123456789'.replace(/\d{3,}/, 'x'); //x
十、非貪婪模式
儘可能少的匹配。
如果我們想要最低限度的替換呢?
// 非貪婪模式使用 ? 儘可能的往少的方面去匹配
'12345678'.replace(/\d{3,6}?/g, 'x'); //xx78
'123456789'.replace(/\d{3,6}?/g, 'x'); //xxx
因為有g
標誌,會匹配這段字串裡所有符合規則的字串。
第一個規則/\d{3,6}?/g
,12345678
中有兩個符合條件的字串,是123
和456
。所以替換結果是xx78
。
第二個規則/\d{3,6}?/g
,123456789
中有三個符合條件的字串,是123
、456
和789
。所以替換結果是xxx
。
十一、分組
括號裡的一些規則,分為一組。
我想替換連續出現3次的字母
和數字
。
//沒有分組的情況下,後面的量詞,只是表示匹配3次數字。
'a1b2d3c4'.replace(/[a-z]\d{3}/g, '*'); //a1b2d3c4
//有分組的情況下,分組後面的量詞,表示符合這個分組裡規則的字串,匹配3次。
'a1b2d3c4'.replace(/([a-z]\d){3}/g, '*'); //*c4
1、或
分組裡有兩種規則,只要滿足其中一種即可匹配。
//我想把ijaxxy和ijcdxy都替換成*
'ijabxyijcdxy'.replace(/ij(ab|cd)xy/g, '*'); //**
2、反向引用
可以把分組視為變數,來引用。
//我想把改變年月日之間的分隔符
'2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3'); //2018/5/22
//我想替換日期,並且更改順序
'2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$2/$3/$1'); //5/22/2018
3、忽略分組
忽略掉分組,不捕獲分組,只需要在分組內加上?:
// 忽略掉匹配年的分組後,匹配月的分組變成了$1,日的分組變成了$2
'2018-5-22'.replace(/(?:\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3'); //5/22/$3
十二、前瞻
正則表示式從文字頭部向尾部開始解析,文字尾部方向,稱為“前”。 前瞻就是在正在表示式匹配到規則的時候,向前檢查是否符合斷言,後顧/後瞻方向相反。 JavaScript不支援後顧。 符合和不符合特定斷言稱為
肯定/正向
匹配和否定/負向
匹配。
| 名稱 | 正則 | 含義 |
| :-: | :-- | :-- |
| 正向前瞻 | exp(?=assert)
| |
| 負向前瞻 | exp(?!assert)
| |
| 正向後顧 | exp(?<=assert)
| JavaScript不支援 |
| 負向後顧 | exp(?<!assert)
| JavaScript不支援 |
例子
有這樣一個單詞字元
+數字
格式的字串,只要滿足這種格式,就把其中的單詞字元替換掉。
'a1b2ccdde3'.replace(/\w(?=\d)/g, '*'); //*1*2ccdd*3
有這樣一個單詞字元
+非數字
格式的字串,只要滿足這種格式,就把前面的單詞字元替換掉。
'a1b2ccdde3'.replace(/\w(?!\d)/g, '*'); //a*b*****e*
十三、RegExp物件屬性
global
是否全文搜尋,預設false
。
ignore case
是否大小寫敏感,預設是false
。
multiline
多行搜尋,預設值是false
。
lastIndex
是當前表示式匹配內容的最後一個字元的下一個位置。
source
正則表示式的文字字串。
let reg1 = /\w/;
let reg2 = /\w/gim;
reg1.global; //false
reg1.ignoreCase; //false
reg1.multiline; //false
reg2.global; //true
reg2.ignoreCase; //true
reg2.multiline; //true
十四、RegExp物件方法
1、RegExp.prototype.test()
用來檢視正則表示式與指定的字串是否匹配。返回
true
或false
。
let reg1 = /\w/;
reg1.test('a'); //true
reg1.test('*'); //false
加上g
標誌之後,會有些區別。
let reg1 = /\w/g;
// 第一遍
reg1.test('ab'); //true
// 第二遍
reg1.test('ab'); //true
// 第三遍
reg1.test('ab'); //false
// 第四遍
reg1.test('ab'); //true
// 第五遍
reg1.test('ab'); //true
// 第六遍
reg1.test('ab'); //false
實際上這是因為RegExp.lastIndex
。每次匹配到之後,lasgIndex
會改變。
lastIndex
是正則表示式的一個可讀可寫的整型屬性,用來指定下一次匹配的起始索引。
let reg = /\w/g;
// 每次匹配到,就會把lastIndex指向匹配到的字串後一個字元的索引。
while(reg.test('ab')) {
console.log(reg.lastIndex);
}
// 1
// 2如果大家如果在自學遇到困難,想找一個好的前端學習環境,可以加入我們的前端學習圈:767273102 ,從最基礎的HTML+CSS+JavaScript。jQuery,Ajax,node,angular等到移動端HTML5的專案實戰的資料都有整理,好友都會在裡面交流,分享一些學習的方法和需要注意的小細節。
reg.lastIndex
初始時為0
,第一個次匹配到a
的時候,reg.lastIndex
為1
。第二次匹配到b
的時候,reg.lastIndex