一篇文章搞定 javascript 正則表達式

前言

正則表達式在平時工做中很是常見,可是它的神奇對於不少程序員可能一直像魔法同樣的存在,工做中用到的大部分正則都是去網上搜索得來的,再複雜一點看着文檔費時費力的拼湊一下。是否是深有感觸了?一次在網上看到有關正則的視頻,讓我收貨頗多,當時認真記錄了筆記和本身的感悟,也但願給更多須要的童鞋帶來幫助。文章從零開始講正則,致使有點長,能夠收藏零碎時間慢慢看,認真看完絕對受益不淺。文章首發於個人博客,如下是正文:javascript

Regular Expression 使用單個字符串來描述、匹配一系列符合某個語法規則的字符串。說簡單了就是按照某種規則去匹配符合條件的字符串。這裏先推薦一個學習正則表達式的在線工具:regexper.com/,網站利用圖像和英文解…^\d{4}[/-]\d{2}[/-]\d{2}$在工具中是這樣顯示的:java

是否是很是直觀~git

RegExp對象

javaScript中經過內置對象 RegExp 支持正則表達式,有兩種方法實例化 RegExp 對象:程序員

  1. 字面量
  2. 構造函數

1. 字面量

假設你須要把一句英文裏面的小寫is匹配成大寫的 IS,你能夠這樣作:github

var reg = /\bis\b/;
var text = 'He is a boy, This is a dog. Where is she?';
var result = text.replace(reg,'IS');
console.log(result) //He IS a boy, This is a dog. Where is she?
複製代碼

這樣就把第一個英文單詞'is'替換成了'IS',假如你想把該句中全部的單詞'is'都替換成'IS',應該這樣寫:正則表達式

var reg = /\bis\b/g;
var text = 'He is a boy, This is a dog. Where is she?';
var result = text.replace(reg,'IS');
console.log(result) //He IS a boy, This IS a dog. Where IS she?
複製代碼

在正則的末尾加上'g'就好,'g'表示global,是全局匹配的意思。'g'是正則表達式的一個修飾符,修飾符有:數組

  • 'g': global 全文搜索,不添加,搜索到第一個中止
  • 'i': ignore case 忽略大小寫,默認大小寫敏感
  • 'm': multiple 多行搜索 ,檢測字符串中的換行符,主要是影響字符串開始標識符^和結束標識符$的使用

可能你會想,爲何句子中的'This'中的is沒有被匹配成功呢,這就是咱們'\b'的功勞了。函數

'\b':匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,「er\b」能夠匹配「never」中的「er」,但不能匹配「verb」中的「er」。工具

這裏的正則在'is'的先後都有'\b',這樣就只能匹配單詞'is'了。學習

構造函數

假若你須要使用構造函數的方式實例化正則,則上面的字面量形式能夠改爲這樣:

var reg = new RegExp('\\bis\\b','g');
var text = 'He is a boy, This is a dog. Where is she?';
var result = text.replace(reg,'IS');
console.log(result) //He IS a boy, This IS a dog. Where IS she?
複製代碼

用這種方式就不須要'/'符號開始和結尾以表示是正則了。可是裏面的'\'等特殊字符須要用'\'轉義。

'\':將下一個字符標記爲一個特殊字符、或一個原義字符、或一個向後引用、或一個八進制轉義符。例如,「n」匹配字符「n」。「\n」匹配一個換行符。串行「\\」匹配「\」而「\(」則匹配「(」。

元字符

正則表達式由兩種基本字符類型組成:

  • 原義文本字符,即表明它本來含義的字符
  • 元字符,元字符是在正則表達式中有特殊含義的非字母字符,例如上文提到的'\b',表示匹配單詞邊界,並非匹配'\b',在正則中主要存在這些特殊字符:*,+,?,$,^,.,|,\,(,),{,},[,]

字符類(字符集合)

通常狀況下,正則表達式一個字符對應字符串一個字符,例如:ab\t就是匹配字符串'ab'+'tab'

可是更多的時候,咱們匹配的並非某個字符,而是符合一系列特徵的字符串。這時候,咱們就可使用元字符'[]'來構建一個簡單的類,所謂類是指符合某些特性的對象,一個泛指,而不是特指某個字符,例如:表達式'[abc]'把字符a或b或c歸爲一類,表達式能夠匹配這樣的字符。

var reg = /[abc]/g;
var text = 'a1b2c3d4';
var result = text.replace(reg,'X');
console.log(result); //X1X2X3d4
複製代碼

這樣咱們匹配的就是否是abc這樣三個字符了,而是abc中任何一個字符,這就是元字符的一個應用。

字符類取反

使用元字符'^'建立 反向類/負向類

反向類的意思是不屬於類的內容,表達式'[^abc]'表示不是字符a或b或c的內容,例如:

var reg = /[^abc]/g;
var text = 'a1b2c3d4';
var result = text.replace(reg,'X');
console.log(result); //aXbXcXXX
複製代碼

範圍類

假若咱們須要用字符類匹配數字,按照前面的匹配方式,書寫可能會很麻煩,須要這樣:'[0123456789]',對於 a 到 z 的字符更是如此。

爲此,正則表達式給咱們提供了範圍類,咱們可使用[a-z]來鏈接兩個字符,表示從a到z的任意字符,這是一個閉區間,包含 a 和 z 自己。

var reg = /[a-z]/g;
var text = 'a1b2c3d4z9';
var result = text.replace(reg,'Q');
console.log(result); //Q1Q2Q3Q4Q9
複製代碼

能夠發現,這樣就方便了許多。

此外,在'[]'組成的類的內部是能夠連寫的[a-zA-Z],這樣就造成了大寫字母小寫字母徹底匹配:

var reg = /[a-zA-Z]/g;
var text = 'a1b2c3d4z9ASDFHDFH';
var result = text.replace(reg,'Q');
console.log(result); //Q1Q2Q3Q4Q9QQQQQQQQ
複製代碼

有些童鞋可能會想,我想連範圍類裏面的'-'字符也一塊兒匹配了,咱們該怎麼作?

其實也很簡單,例如:

var reg = /[0-9]/g; //這樣是跟前面同樣的結果,不行
var text = '2018-05-13';
var result = text.replace(reg,'Q');
console.log(result); //QQQQ-QQ-QQ

var reg = /[0-9-]/g; //只要在後面另外加一個‘-’符號就能夠了
var text = '2018-05-13';
var result1 = text.replace(reg,'Q');
console.log(result1); //QQQQQQQQQQ
複製代碼

預約義類及邊界

預約義類

正則表達式提供預預約義類來匹配常見的字符類,讓咱們書寫更方便。

字符 等價類 含義
. [^\r\n] 除了回車符和換行符以外的全部字符
\d [0-9] 數字字符
\D [^0-9] 非數字字符
\s [\t\n\x0B\f\r] 空白符
\S [^\t\n\x0B\f\r] 非空白符
\w [a-zA-Z_0-9] 單詞字符(字母、數字、下劃線)
\W [^a-zA-Z_0-9] 非單詞字符

digit 數字 '\d', space空白 '\s',word字母 '\w',大寫取反,媽媽不再用擔憂我記錯了

來看一個實際的例子,匹配一個 ab+數字+任意字符 的字符串:

var reg = /ab\d./; //以前咱們可能會這樣寫:ab[0-9][^\r\n]
var text = 'absdlkjflab91323';
var result = text.replace(reg,'AAAA');
console.log(result); //absdlkjflAAAA323
複製代碼

邊界

除了預約義類,正則表達式還提供了幾個經常使用的邊界字符。

字符 等價類
^ 以xxx開始
$ 以xxx結束
\b 單詞邊界
\B 非單詞邊界

咱們在第一個例子中用到過'\b'單詞邊界,這裏咱們作一個跟上面第一個例子相反的,只把'This'中的'is'替換爲'IS'

var reg = /\Bis\b/g;
var text = 'He is a boy, This is a dog. Where is she?';
var result = text.replace(reg,'IS');
console.log(result) //He is a boy, ThIS is a dog. Where is she?
複製代碼

而後咱們在說一下'^'和'$',在類'[]'中'^'表示取反,可是不在類中的時候'^'表示以xxx開始,'$'表示以xxx結束,這兩個邊界字符通常放在正則的開始和結束位置。

//先看沒加^或$的狀況
var reg = /@./g;
var text = '@123@ab@A';
var result = text.replace(reg,'Q');
console.log(result); //Q23QbQ

//添加^的狀況
var reg = /^@./g;
var text = '@123@ab@A';
var result1 = text.replace(reg,'Q');
console.log(result1); //Q23@ab@A

//添加$的狀況
var reg = /@.$/g;
var text = '@123@ab@A';
var result1 = text.replace(reg,'Q');
console.log(result1); //@123@abQ
複製代碼

上面的例子,若是'^'和'$'都加上的話,是匹配不成功的,由於沒有符號的字符串能夠匹配成功,童鞋們能夠本身試試。

這裏再結合多行匹配舉一個例子:

var reg = /^@\d./g;
var text= '@123\n@456\n@789';
var result = text.replace(reg,'Q');
console.log(result);// Q3 @456 @789
複製代碼

這裏你會發現,並無像咱們預期的把三行中符合預期的字符都替換成功,只有第一行成功匹配替換了,這是爲何呢?

這是由於,換行符在咱們看來是換了一行寫而已,可是對於程序處理字符串的時候,換行符就是一個普通的字符,並不算是咱們認爲的新的一行。這時候咱們的修飾符'm'就能夠大展身手了:

var reg = /^@\d./gm;
var text= '@123\n@456\n@789';
var result = text.replace(reg,'Q');
console.log(result);// Q3 @6 @9
複製代碼

量詞

假若咱們但願匹配一個連續出現20次的數字的字符串,經過咱們以前學習的知識,咱們可能會寫出連續20個'\d'。假如20次你還能夠接受,那100次,1000次,甚至更屢次,你怎麼辦?

爲了解決這個問題,正則表達式引入了量詞的概念,下面是一些量詞和他們的含義:

字符 含義
出現零次或一次(最多出現一次)
+ 出現一次或者屢次(至少出現一次)
* 出現零次或者屢次(任意次)
{n} 出現n次
{n,m} 出現n到m次
{n,} 至少出現n次

咱們能夠拿文章開始的日期正則舉個栗子:

var reg = /\d{4}[/-]\d{2}[/-]\d{2}/g;
var text = '2018-02-23,2018/02/24,2018~02/25';
var result = text.replace(reg,'匹配正確日期格式');
console.log(result);//匹配正確日期格式,匹配正確日期格式,2018~02/25
複製代碼

貪婪模式

正則表達式默認是貪婪模式,即每次匹配都儘量的匹配多的字符,直到匹配失敗爲止。

舉個栗子:

var reg = /\d{3,6}/g;
var text = '12345678';
var result = text.replace(reg,'X');
console.log(result);//X78
複製代碼

從上面能夠看出,正則表達式匹配了'123456',而不是'123','1234','12345',儘量多的匹配了6次,即貪婪模式。

假若咱們但願它只匹配3次,即儘量少的匹配,一旦匹配成功再也不繼續嘗試,即非貪婪模式須要怎麼作呢?

很簡單,在量詞後面加上'?'便可,咱們再用剛纔的例子試一下:

var reg = /\d{3,6}?/g;
var text = '12345678';
var result = text.replace(reg,'X');
console.log(result);//XX78
複製代碼

分組

假如咱們有這麼一個場景:匹配字符串 Byron 連續出現3次的場景,根據前面所學,咱們可能會這樣寫:Byron{3}

可是這樣是錯誤的,試試你會發現只有Byronnn才能匹配成功,即最後的n重複了3次,並不能匹配整個單詞重複三次的狀況:

var reg = /Byron{3}/g;
var text = 'ByronByronByronnn';
var result = text.replace(reg,'0');
console.log(result);//ByronByron0
複製代碼

那麼,咱們要怎麼匹配Byron連續出現3次的狀況呢,這時候,正則表達式的分組'()'就幫咱們解決了這個問題:

var reg = /(Byron){3}/g;
var text = 'ByronByronByronnn';
var result = text.replace(reg,'0');
console.log(result);//0nn
複製代碼

有時候,咱們可能會須要在匹配時用到或者的關係,利用以前的'[]'字符類(字符集合)可能只能匹配單個字符的或者關係,好比匹配a或b,你能夠這樣寫:'[ab]',可是若是你須要匹配的是一整個單詞的或者關係呢,可能'[]'就很差使了。這時候,咱們用'|'能夠達到或的效果:

//匹配單詞Byron或者Casper
var reg = /Byron|Casper/g;
var text = 'ByronCasper'
var result = text.replace(reg,'X');
console.log(result);//XX

//匹配Byr+on或Ca+sper
var reg = /Byr(on|Ca)sper/g;
var text = 'ByronsperByrCasper'
var result1 = text.replace(reg,'X');
console.log(result1);//XX
複製代碼

反向引用

假如咱們有這樣一個需求:把日期'2015-12-25'替換成'12/25/2015',若是是你,你如今會怎麼作呢?

你可能會這樣寫:

var reg = /\d{4}-\d{2}-\d{2}/g;
var text = '2015-12-25'
var result = text.replace(reg,'12/25/2015');
console.log(result);//12/25/2015
複製代碼

可是上面這樣的寫法,你只可以匹配到'2015-12-25'了,不能再匹配別的日期了,'2015-12-25'是會變的,這樣就達不到需求了。

這時候,正則的反向引用就能夠取到做用了。表達式在匹配時,表達式引擎會將小括號 "( )" 包含的表達式所匹配到的字符串記錄(分組捕獲)下來。在獲取匹配結果的時候,小括號包含的表達式所匹配到的字符串能夠單獨獲取。

在js中正則匹配成功的字符串能夠用$1表示第一次匹配成功,$3表示第三次匹配成功的字符,以此類推至$99)。因而,上面的例子就能夠這樣寫了:

var reg = /(\d{4})-(\d{2})-(\d{2})/g;
var text = '2015-12-25'
var result = text.replace(reg,'$2/$3/$1');
console.log(result);//12/25/2015
複製代碼

忽略分組

在上面的反向引用中,咱們默認是根據'()'所有捕獲記錄爲$1~$99的,假若咱們想忽略某個捕獲要怎麼辦呢?

不但願捕獲某些分組,只須要在分組內加上'?:'就能夠了。

var reg = /(?:Byron)(\d{4})-(\d{2})-(\d{2})/g;
var text = 'Byron2016-12-05'
var result = text.replace(reg,'$2/$3/$1');
console.log(result);//12/05/2016
複製代碼

這時候的$1不是Byron,而是2016了。

前瞻

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

符合和不符合斷言稱爲確定/正向匹配和否認/負向匹配。

上面是前瞻的概念,是否是看完有點暈?我看完也有點暈...我來解釋一下:假如你須要匹配一個名字叫「張三」的人,之前咱們多是從一堆人中找出名字是「張三」的揪出來就好了,可是前瞻就是要求你,揪出的人的名字叫「張三」還不夠,還必須「張三」的父親必須叫「張二」或者其它特定條件,這樣就是前瞻了,相似的,後瞻就是名字是張三還不夠,兒子還必須叫「小張」等。

是否是有點明白了?不過須要注意的是,在javascript中是不支持後顧/後瞻的,因此咱們也不須要關心了。(這裏糾正一下,在 ES2018(ES9) 中已經支持後瞻和命名分組了)

至於符合/不符合斷言,能夠解釋爲:好比匹配要求名字叫「張三」,而且呢他父親不叫「張二」,對於符合的咱們就叫正向/確定匹配,不符合的就叫負向/否認匹配。

咱們再用表格說明一下:

名稱 正則 含義
正向前瞻 exp(?=assert) 咱們匹配符合了exp部分的表達式,而後還不算完,必須也匹配斷言部分('()'內部,'='後面的正則),纔算成功
負向前瞻 exp(?!assert) 咱們匹配符合了exp部分的表達式,而後還不算完,必須也匹配斷言部分('()'內部,'!'後面的正則),纔算成功
正向後顧 exp(?<=assert) javascript不支持
負向後顧 exp(?<!assert) javascript不支持

如今是否是清楚了?若是還不夠明白,沒事,咱們再舉個栗子:

var reg = /\w(?=\d)/g;
var text = 'a2*3';
var result = text.replace(reg,'X');
console.log(result);//X2*3
複製代碼

須要注意,咱們斷言裏面內容只是做爲匹配的條件之一,也是必須的條件,可是匹配的本質只匹配"()"前面的正則,因此上面的結果爲:'X2*3',而不是'X*3'。若是要匹配結果爲後者,咱們按原來的寫法就好了var reg = /\w\d/g;,不是嗎?

對象屬性

咱們在用正則表達式相關的方法時,常常會用到正則表達式相關的一些對象屬性,下面咱們總結一下正則表達式相關的對象屬性:

  • golbal: 是否全文搜索,默認false
  • ignore case: 是否大小寫敏感,默認false
  • multiline: 多行搜索,默認false
  • lastIndex: 是當前表達式匹配內容的最後一個字符的下一個位置
  • source: 正則表達式的文本字符串

其中前面三個咱們在上文中已經提到過了,source的話,咱們一塊兒結合起來看看代碼:

var reg1 = /\w/;
var reg2 = /\w/gim;

console.log(reg1.global);//false
console.log(reg1.ignoreCase);//false
console.log(reg1.multiline);//false

console.log(reg2.global);//true
console.log(reg2.ignoreCase);//true
console.log(reg2.multiline);//true

console.log(reg1.source);//\w
console.log(reg2.source);//\w
複製代碼

golbal、ignore case、multiline默認都是false,而source就是你寫的正則字符串文本了。

至於lastIndex,咱們先來看一個例子:

var reg1 = /\w/;
var reg2 = /\w/g;

console.log(reg1.test('a'));//true
console.log(reg1.test('a'));//true
console.log(reg1.test('a'));//true
//... 無論執行多少次都是true

console.log(reg2.test('ab'));//true
console.log(reg2.test('ab'));//true
console.log(reg2.test('ab'));//false
console.log(reg2.test('ab'));//true
console.log(reg2.test('ab'));//true
console.log(reg2.test('ab'));//false
//... 循環true true false
複製代碼

對於上面的結果,是否是很奇怪?這就是'lastIndex'做用的結果了,(至於test方法,不懂的童鞋能夠往下翻一番)。咱們來輸出'lastIndex'試試:

var reg2 = /\w/g;
while(reg2.test('ab')){
  console.log(reg2.lastIndex); // 1 2
}
複製代碼

能夠發現,'lastIndex'是在不斷髮生變化的,即當前匹配結果的最後一個字符的下一個位置,這裏第一次匹配到'a'字符,匹配結果的最後一位字符也是'a','a'字符的下一個位置的index就是1了。相似的第二次匹配'b',匹配結果的最後一位字符也是'b','b'字符的下一個位置的index就是2。如今再看看概念,是否是明白了許多?

因此說,正則每次匹配並非從頭開始的,而是從上次的結果日後找,看看後面還有沒有,有的話繼續匹配,固然這必須是在'g'全局匹配的基礎上,否則每次匹配都是從頭開始的。

正則表達式RegExp對象自己的方法

RegExp對象自帶的方法總共有三個:

  1. test: 檢索字符串中指定的值。返回 true 或 false
  2. exec: 檢索字符串中指定的值。返回找到的值,並肯定其位置
  3. compile: 編譯正則表達式(不經常使用)

test方法

test() 方法用於測試字符串參數中是否存在匹配正則表達式模式的字符串,若是存在則返回 true ,不然返回 false 。

語法爲RegExpObject.test(string),若是字符串 string 中含有與 RegExpObject 匹配的文本,則返回 true,不然返回 false。

舉個栗子:

var str = "good good study, day day up";
var reg = new RegExp("study");
var result = reg.test(str);
console.log(result);//true
複製代碼

exec方法

exec() 方法用於使用正則表達式模式對字符串執行搜索,並將更新全局 RegExp 對象的屬性以反映匹配結果。

語法爲RegExpObject.exec(string),若是字符串 string 中含有與 RegExpObject 匹配的文本,則返回一個數組,其中存放匹配的結果。若是未找到匹配,則返回值爲 null。

而且,數組存在兩個額外的屬性:

  1. index: 聲明匹配文本的第一個字符的位置
  2. input: 存放被檢索的字符串 String

exec()方法比較複雜,全局調用和非全局調用的結果不一樣:

非全局(即不帶'g')調用

  • 調用非全局的 RegExp 對象的exec()時,返回數組
  • 數組中第一個元素是正則表達式匹配的文本
  • 數組中第二個元素是與 RegExpObject 的第一個子表達式相匹配的文本(若是有的話)
  • 數組中第三個元素是與 RegExp 對象的第二個子表達式相匹配的文本(若是有的話,以此類推

看起來是否是又有點暈?不怕,咱們來看看例子:

var reg3 = /\d(\w)\d/;
var str = '1a2b3c4d5e';
var arr = reg3.exec(str);
console.log(reg3.lastIndex + '\t' + arr.index + '\t' + arr.toString());//0 0 1a2,a
複製代碼

即輸出結果爲: lastIndex(這裏爲0是由於非全局匹配下lastIndex實際上是不生效的),匹配文本的第一個字符的位置(額外屬性index,這裏第一個字符爲'1')和匹配結果數組('1a2'爲匹配文本,'a'爲子表達式'(\w)'的匹配結果,這裏不存在第二個子表達式'()',因此數組裏面沒有第三個匹配結果的值)。是否是清楚了許多?

全局調用

  • exec() 會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。
  • 當 exec() 找到了與表達式相匹配的文本時,在匹配後,它將把 RegExpObject 的 lastIndex 屬性設置爲匹配文本的最後一個字符的下一個位置。
  • 這就是說,你能夠經過反覆調用 exec() 方法來遍歷字符串中的全部匹配文本。
  • 當 exec() 再也找不到匹配的文本時,它將返回 null,並把 lastIndex 屬性重置爲 0。
  • 注意:若是在一個字符串中完成了一次模式匹配以後要開始檢索新的字符串,就必須手動地把 lastIndex 屬性重置爲 0。

咱們一樣來舉個栗子:

var reg4 = /\d(\w)(\w)\d/g;
var str = '$1az2bb3cy4dd5ee';

while(arr = reg4.exec(str)){
  console.log(reg4.lastIndex + '\t' + arr.index + '\t' + arr.toString());
  //5 1 1az2,a,z
  //11 7 3cy4,c,y
}
複製代碼

這裏我就不在解釋結果的含義了,相信童鞋們看完上面的非全局的解釋就能夠理解這裏全局的狀況了。

compile方法

compile() 方法用於在腳本執行過程當中編譯正則表達式,也可用於改變和從新編譯正則表達式。這個咱們在平時工做中通常不會用到(我至今沒看到過...);

它的語法爲:RegExpObject.compile(regexp,modifier),其中參數'regexp'爲正則表達式,參數'modifier'爲規定匹配的類型。"g" 用於全局匹配,"i" 用於區分大小寫,"gi" 用於全局區分大小寫的匹配(摘錄於W3C)。

咱們來看一個例子:

var str = "Every man in the world! Every woman on earth!";
var reg = /man/g;
var str2 = str.replace(reg,"person");
console.log(str2)

var reg2=/(wo)?man/g;
reg.compile(reg2);
console.log(reg.source);//(wo)?man 這裏能夠看到reg經過compile編譯爲reg2同樣了
var str2=str.replace(reg,"person");
console.log(str2);
複製代碼

上面的意思就是:在字符串中全局搜索 "man",並用 "person" 替換。而後經過 compile() 方法,改變正則表達式reg爲reg2,並繼續利用正則改變後的正則表達式reg,用 "person" 替換 "man" 或 "woman"。

至於爲何用compile動態改正則,那跟新建有啥區別呢?

我查了查資料是這麼說的:若是指定的正則表達式須要屢次重複使用,那麼編譯正則表達式將會提升代碼的執行效率,不過若是僅僅執行一次或者少數幾回,那麼將不會有明顯的效果,compile提升了正則表達式的適應性!

支持正則表達式的 String 對象的方法

支持正則表達式的 String 對象的方法有:

  • search: 檢索與正則表達式相匹配的值
  • match: 找到一個或多個正則表達式的匹配。
  • replace: 替換與正則表達式匹配的子串。
  • split: 把字符串分割爲字符串數組。

search

search() 方法用於檢索字符串中指定的子字符串,或檢索與正則表達式匹配的子字符串

語法爲stringObject.search(regexp),結果返回 stringObject 中第一個與 regexp 相匹配的子串的起始位置index,若是沒有找到任何匹配的子串,則返回 -1。

須要注意的是,search() 方法不執行全局匹配,它將忽略修飾符'g',而且老是從字符串的開始進行檢索。

來看一個例子:

var str = 'a1b2c3d4';
console.log(str.search('1')); //1
console.log(str.search('10')); //-1
console.log(str.search(/b2/)); //2
console.log(str.search(/\w\d/g)); //0
console.log(str.search(/\w\d/g)); //0 忽略'g',執行屢次未返回不一樣結果
複製代碼

match

match() 方法將檢索字符串,以找到一個或多個與 RegExp 匹配的文本,在 RegExp 是否有修飾符'g'影響很大。該方法相似 indexOf() 和 lastIndexOf(),可是它返回指定的值,而不是字符串的位置。

語法爲stringObject.match(searchvalue)或stringObject.match(regexp),結果返回存放匹配結果的數組。該數組的內容依賴於 regexp 是否具備全局標誌 g。

match() 方法也分全局調用和非全局調用:

非全局調用

  • 若是 regexp 沒有標誌 g ,那麼 match() 方法就只能在字符串中執行匹配一次
  • 若是沒有找到任何匹配文本,返回 null
  • 不然它將返回一個數組,其中存放了與它找到的匹配文本有關的信息:
  • 數組的第 0 個元素存放的是匹配文本,而其他的元素存放的是與正則表達式的子表達式匹配的文本。(這裏與前面說的exec()方法相似)

而且,數組也存在兩個額外的屬性(與 exec() 方法基本相同):

  1. index: 聲明匹配文本的第一個字符的位置
  2. input: 聲明對 stringObject 的引用

下面是舉例:

var reg3 = /\d(\w)\d/;
var str = '1a2b3c4d5e';
var arr = str.match(reg3);
console.log(reg3.lastIndex + '\t' + arr.index + '\t' + arr.toString());//0 0 1a2,a
複製代碼

能夠看到結果都與 exec() 方法同樣,只是字符串和正則的位置交換了一下。

全局調用

全局調用就和 exec() 不一樣了:

  • 若是 regexp 具備標誌 g 則 match() 方法將執行全局檢索,找到字符串中全部匹配的子字符串
  • 沒有找到任何匹配的子字符串則返回 null
  • 若是找到了一個或者多個匹配字串,則返回一個數組
  • 數組元素中存放的是字符串中全部匹配的字串,並且也沒有index屬性和input屬性

簡單的說,就是返回一個數組,數組中放着全部匹配結果。

var reg4 = /\d(\w)(\w)\d/g;
var str = '$1az2bb3cy4dd5ee';
var arr = str.match(reg4)
console.log(arr); // ["1az2", "3cy4"]
console.log(reg4.lastIndex + '\t' + arr.index) //0 undefined
複製代碼

能夠看出,match() 方法功能沒有 exec() 方法返回那麼多各類信息,可是若是隻要結果數組,match() 方法效率會高一些。

split

對於split()方法我就不詳細說明了,咱們常常用它把字符串分割爲數組。

var str = 'a,b,c,d';
var arr = str.split(',');
console.log(arr); //['a','b','c','d']
複製代碼

可是你可能不知道,咱們在一些複雜狀況下咱們可使用正則表達式解決

var str = 'a1b2c3d';
var arr = str.split(/\d/);
console.log(arr); //['a','b','c','d']
複製代碼

上面可能還看不出 spilt() 方法用正則分割的有點,可是若是複雜一點的分割呢,好比:

var str = 'a1b&c|d&e';
var arr = str.split(/[\d|&]/);
console.log(arr); //['a','b','c','d','e']
複製代碼

這樣是否是看出了用正則的優點呢?

小知識:其實,咱們在用 split() 分割字符','的時候,split() 方法也是把',' 隱士轉換成正則'/,/'的, search() 方法和 replace() 方法也是同樣的。

replace

replace() 方法用於在字符串中用一些字符替換另外一些字符,或替換一個與正則表達式匹配的子串。

語法爲stringObject.replace(regexp/substr,replacement),結果返回一個新的字符串,是用 replacement 替換了 regexp 的第一次匹配或全部匹配以後獲得的。

對於 replace() 方法,它有三種使用方式:

  1. String.prototype.replace(str,replaceStr);
  2. String.prototype.replace(reg,replaceStr);
  3. String.prototype.replace(reg,function);

1和2兩種的使用我就再也不多舉例了,相信若是你認真看完前面的文章,確定最熟悉的就是 replace() 方法了的1、二兩種用法了。 這裏就提一下第3種使用方法。

先說一下String.prototype.replace(reg,function);中 function 的參數含義,function 會在每次匹配替換的時候調用,有四個參數(第二個參數不固定):

  1. 匹配字符串
  2. 正則表達式的分組內容,沒有分組則沒有該參數、
  3. 匹配項在字符串中的 index
  4. 原字符串

照例來舉兩個個栗子看看:

var str = 'a1b2c3d4e5';
var reg = /\d/g;
var arr = str.replace(reg,function(match, index, origin){
  console.log(index);// 1 3 5 7 9
  return parseInt(match) + 1;
})
console.log(arr);//a2b3c4d5e6 把每次匹配到的結果+1替換


var str = 'a1b2c3d4e5';
var reg = /(\d)(\w)(\d)/g;
var arr = str.replace(reg,function(match, group1, group2, group3, index, origin){
  console.log(match);// 1b2 3d4
  return group1 + group3;
})
console.log(arr);//a12c34e5 去除了每次匹配到的group2
複製代碼

文章到這裏就所有結束了,每一個例子都是實際測試輸出結果,碼了很久很久......但願文章對您有幫助,我就心滿意足了~~

相關文章
相關標籤/搜索