全方面系統認識JavaScript正則表達式

1、正則表達式簡介

一、什麼是正則表達式

正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式一般被用來檢索、替換那些符合某個模式(規則)的文本。正則表達式

簡單的說,就是按照某種規則去匹配符合條件的字符串。

二、可視化正則表達式工具

Regexper:https://regexper.com/函數

2、RegExp對象

實例化 RegExp的兩種方式。

兩種方式定義RegExp對象。工具

一、字面量

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 表明大小寫不敏感,默認大小寫敏感。

二、構造函數

let reg = new RegExp('\\bis\\b', 'g');

由於JavaScript字符串中\屬於特殊字符,須要轉義。prototype

3、元字符

把元字符看成轉義字符。

正則表達式有兩種基本字符類型組成。3d

  • 原義文本字符
  • 元字符

一、原義文本字符

表示本來意義上是什麼字符,就是什麼字符。code

二、元字符

是在正則表達式中有特殊含義的非字母字符。
* + ? $ ^ . | \ ( ) { } [ ]regexp

字符 含義
\t 水平製表符
\v 垂直製表符
\n 換行符
\r 回車符
\0 空字符
\f 換頁符
\cX 控制字符,與X對應的控制字符(Ctrl + X)

相似於轉義字符。對象

4、字符類

表示符合某種特性的字符類別。

使用元字符[]能夠構建一個簡單的類。
所謂類是指符合某些特性的對象,一個泛指,而不是某個字符。索引

例子

表達式[abc]把字符abc歸爲一類,表達式能夠匹配這一類中的任意一個字符。ip

// replace() 方法用於在字符串中用一些字符替換另外一些字符,或替換一個與正則表達式匹配的子串。
'a1b2c3d4e5'.replace(/[abc]/g, '0');  //010203d4e5

字符類取反

咱們想要替換不是abc中任意一個字符的字符。

// 元字符 ^ 建立一個 反向類/負向類
'abcdefg'.replace(/[^abc]/g, '0');  //abc0000

5、範圍類

匹配這一個範圍內的字符。

若是咱們想要匹配數字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, '*');  //*********

6、預約義類

一些已經定義的類,能夠直接使用。
字符 等價類 含義
. [^\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

7、單詞邊界

字符 含義
^ 以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

8、量詞

用來處理連續出現的字符串。
字符 含義
? 出現零次或一次(最多出現一次)
+ 出現一次或屢次(至少出現一次)
* 出現零次或屢次(任意次)
{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

9、貪婪模式

儘量多的匹配。

有這樣的一種場景下的正則表達式,/\d{3,6}/該替換3個數字仍是6個數字呢,四、5個數字?

// 貪婪模式會盡量的往多的方面去匹配
'123456789'.replace(/\d{3,6}/, 'x');  //x789
'123456789'.replace(/\d+/, 'x');  //x
'123456789'.replace(/\d{3,}/, 'x');  //x

10、非貪婪模式

儘量少的匹配。

若是咱們想要最低限度的替換呢?

// 非貪婪模式使用 ? 儘量的往少的方面去匹配
'12345678'.replace(/\d{3,6}?/g, 'x');  //xx78
'123456789'.replace(/\d{3,6}?/g, 'x');  //xxx

由於有g標誌,會匹配這段字符串裏全部符合規則的字符串。
第一個規則/\d{3,6}?/g12345678中有兩個符合條件的字符串,是123456。因此替換結果是xx78
第二個規則/\d{3,6}?/g123456789中有三個符合條件的字符串,是123456789。因此替換結果是xxx

11、分組

括號裏的一些規則,分爲一組。

我想替換連續出現3次的字母數字

//沒有分組的狀況下,後面的量詞,只是表示匹配3次數字。
'a1b2d3c4'.replace(/[a-z]\d{3}/g, '*');  //a1b2d3c4
//有分組的狀況下,分組後面的量詞,表示符合這個分組裏規則的字符串,匹配3次。
'a1b2d3c4'.replace(/([a-z]\d){3}/g, '*');  //*c4

一、或

分組裏有兩種規則,只要知足其中一種便可匹配。

//我想把ijaxxy和ijcdxy都替換成*
'ijabxyijcdxy'.replace(/ij(ab|cd)xy/g, '*');  //**

二、反向引用

能夠把分組視爲變量,來引用。

//我想把改變年月日之間的分隔符
'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

三、忽略分組

忽略掉分組,不捕獲分組,只須要在分組內加上?:

// 忽略掉匹配年的分組後,匹配月的分組變成了$1,日的分組變成了$2
'2018-5-22'.replace(/(?:\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3');  //5/22/$3

12、前瞻

正則表達式從文本頭部向尾部開始解析,文本尾部方向,稱爲「前」。
前瞻就是在正在表達式匹配到規則的時候,向前檢查是否符合斷言,後顧/後瞻方向相反。
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*

十3、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

十4、RegExp對象方法

一、RegExp.prototype.test()

用來查看正則表達式與指定的字符串是否匹配。返回 truefalse
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

reg.lastIndex初始時爲0,第一個次匹配到a的時候,reg.lastIndex1。第二次匹配到b的時候,reg.lastIndex2

相關文章
相關標籤/搜索