JavaScript學習筆記整理(13):正則表達式

2018-06-19 13:51 更新

正則表達式(regular expression)是一個描述字符模式的對象。JavaScript的RegExp類表示正則表達式,String和RegExp都定義了方法。


1.1 正則表達式的定義
正則表達式有兩種方法定義:
一種是使用正則表達式直接量,將其包含在一對斜杠(/)之間的字符。

var pattern = /s$/;

另一種是使用RegExp()構造函數(shù)。

var pattern = new RegExp('s');

上面兩種方法是等價的,用來匹配所有以字母“s”結尾的字符串。

正則表達式的模式規(guī)則是由一個字符序列組成的,所有字母和數(shù)字都是按照字面含義進行匹配的。

1.1.1 直接量字符
JavaScript正則表達式語法也支持非字母的字符匹配,這些字符需要通過反斜杠(\)作為前綴進行轉義。
有如下直接量字符:

\0 匹配null字符(\u0000)。

[\b] 匹配退格鍵(\u0008),不要與\b混淆。

\t 匹配制表符tab(\u0009)。  

\n 匹配換行鍵(\u000A)。 

\v 匹配垂直制表符(\u000B)。  

\f 匹配換頁符(\u000C)。 

\r 匹配回車鍵(\u000D)。       

\xnn 匹配一個以兩位十六進制數(shù)(\x00-\xFF)表示的字符。  

\uxxx 匹配一個以四位十六進制數(shù)(\u0000-\uFFFF)表示的unicode字符。

\cX 表示Ctrl-[X],其中的X是A-Z之中任一個英文字母,用來匹配控制字符。


1.1.2 字符類
將直接量字符單獨放進方括號就組成了字符類(character class)。一個字符類可以匹配它所包含的任意字符。比如:/[abc]/就和字母“a”、“b”、“c”中的任意一個都匹配。

我們還可以通過“^”符號來定義否定字符類,它匹配所有不包含括號內的字符。定義否定字符類時,將一個“^”符號作為左方括號內的第一個字符。比如: /[^abc]/ 匹配的是“a”、“b”、“c”之外的所有字符。’

字符類還可以使用連字符來表示字符范圍。比如要匹配拉丁字母表中的小寫字母,可以使用 /[a-z]/ ,要匹配拉丁字母表中的任何字母和數(shù)字,則使用 /[a-zA-Z0-9]/ 。

注意:字符類的連字符必須在頭尾兩個字符中間,才有特殊含義,否則就是字面含義。比如,[-9]就表示匹配連字符和9,而不是匹配0到9。

正則表達式的字符類:

[...]  方括號內的任意字符

[^...]不在方括號內的任意字符

.   除換行符和其他Unicode行終止符之外的任意字符

\w  任何ASCII字符組成的單詞,等價于[a-zA-Z0-9]

\W  任何不適ASCII字符組成的單詞,等價于[^a-zA-Z0-9]

\s  任何Unicode空白符

\S  任何非Unicode空白符的字符

\d  任何非ASCII數(shù)字,等價于[0-9]

\D  除了ASCII數(shù)字之外的任何字符,等價于[^0-9]

[\b]  退格直接量

注意:在方括號之內也可以寫上面這些特殊轉義字符。但有一個特例:當轉義符 \b 用在字符類中時,它表示的是退格符,所以要在正則表達式中按照直接量表示一個退格符時,只需使用 /[\b]/ 即可。
1.1.3 重復
在正則模式之后跟隨用以指定字符重復的標記。

正則表達式的重復字符語法:

{n,m}  匹配前一項至少n次,至多m次

{n,}   匹配前一項n次或者更多次,也可以說至少n次

{n}    匹配前一項n次

?      匹配前一項0次或者1次,等價于{0,1}

+      匹配前一項1次或多次,等價于{1,}

*      匹配前一項0次或多次,等價于{0,}

注意:在使用“*”和“?”時,由于這些字符可能匹配0個字符,因此它們允許什么都不匹配。比如:正則表達式/a*/實際上與字符串“bbb”匹配,因為這個字符串含有0個a。

1.1.4 非貪婪的重復
默認情況下,匹配重復字符是盡可能多的匹配,而且允許后續(xù)的正則表達式繼續(xù)匹配,即匹配直到下一個字符不滿足匹配規(guī)則為止,這稱為“貪婪的”匹配。

當然,我們也可以使用正則表達式進行非貪婪匹配,一旦條件滿足,就不再往下匹配。,只須在待匹配的字符后跟隨一個問號即可:“??”、“+?”、“*?”或“{1,5}?”。

/a+/.exec('aaa')  //["aaa"]

/a+?/.exec('aaa')  //["a"]


1.1.5 選擇、分組和引用
正則表達式的語法還包括指定選擇項、子表達式分組和引用前一子表達式的特殊字符。

字符“|”用于分隔供選擇的字符,比如:/ab|cd|ef/可以匹配字符串“ab”,也可以匹配字符串“cd”,還可以匹配字符串“ef”。

注意:選擇項的嘗試匹配次序是從左到右,直到發(fā)現(xiàn)了匹配項。如果左邊的選擇項匹配,就會忽略右邊的匹配項,即使它產生更好的匹配。比如:當正在表達式/a|ab/匹配字符串“ab”時,它只能匹配第一個字符。

圓括號“()”可以把單獨的項組合成子表達式。

帶圓括號的表達式的另一個用途是允許在同一正則表達式的后部引用前面的子表達式,這是通過在字符“\”后加一位或多位數(shù)字來實現(xiàn)的,這個數(shù)字指定了帶圓括號的子表達式在正則表達式中的位置。比如:\1引用的是第一個帶圓括號的子表達式,\3引用的是第三個帶圓括號的子表達式。

/(.)b(.)\1b\2/.test('abcabc')  //true

上面的代碼中,\1表示第一個括號匹配的內容,即第一個(.),匹配的是“a”;\2表示第二個括號(.),匹配的是“b”。

注意:因為子表達式可以嵌套另一個子表達式,所以引用的位置是參與計數(shù)的左括號的位置。比如:(s(ss)),\2表示的是(ss)。

對正則表達式中前一個子表達式的引用,并不是指對子表達式模式的引用,而指的是那個模式相匹配的文本的引用。

/(a|b)c\1/.test('aca')  //true

/(a|b)c\1/.test('acb')  //false

上面的代碼中,由于(a|b)匹配的是a,所以\1所對應的也應該是a。

正則表達式的選擇、分組和引用字符

|    選擇,匹配的是該符號左邊的子表達式或右邊的子表達式

(...)    組合,將幾個項組合為一個單位,這個單位可通過“*”、“+”、“?”和“|”等符號加以修飾,而且可以記住和這個組合相匹配的字符串以供此后的引用使用。

(?...)    只組合,把項組合到一個單位,但不記憶與該組相匹配的字符

\n    和第n個分組第一次匹配的字符相匹配,組是圓括號中的子表達式(也有可能是嵌套的),組索引是從左到右的左括號數(shù),“(?:”形式的分組不編碼


1.1.6 指定匹配位置

除了匹配字符串中的字符外,有些正則表達式的元素匹配的是字符之間的位置,亦可稱為正則表達式的。比如:\b匹配一個單詞的邊界,即位于\w(ASCII單詞)字符和\W(非ASCII單詞)之間的邊界,或位于一個ASCII單詞與字符串的開始或結尾之間的邊界。


正則表達式中的錨字符:

^    匹配字符串的開頭,在多行檢索中,匹配一行的開頭

$    匹配字符串的結尾,在多行檢索中,匹配一行的結尾

\b   匹配一個單詞的邊界

\B   匹配非單詞邊界的位置

(?=p)  零寬正向先行斷言,要求接下來的字符都與p匹配,但不能包括匹配p的那些字符

(?!p)  零寬負向先行斷言,要求接下來的字符不與p匹配


1.1.7  修飾符

正則表達式的修飾符,用以說明高級匹配模式的規(guī)則。修飾符是放在“/”符號之外的,也就是說,它們不是出現(xiàn)在兩條斜杠之間的,而是在第二條斜杠之后。


在JavaScript中,支持三個修飾符:

i   執(zhí)行不區(qū)分大小寫的匹配

g   執(zhí)行一個全局匹配,即找到所有的匹配,而不是在找到第一個之后就停止

m   多行模式匹配,在這種模式下,如果待檢索的字符串包含多行,那么^和$錨字符除了匹配整個字符串的開始和結尾之外,還能匹配每行的開始和結尾

這些修飾符可以任意組合。比如:

/test/ig


1.2 用于模式匹配的String方法

String支持4種使用正則表達式的方法。

search():按照給定的正則表達式進行搜索,返回一個整數(shù),表示第一個與之匹配的字符串的起始位置,如果找不到匹配的子串,將返回-1。

match():返回一個數(shù)組,成員是所有匹配的子字符串。    

replace():按照給定的正則表達式進行替換,返回替換后的字符串。  

split():按照給定規(guī)則進行字符串分割,返回一個數(shù)組,包含分割后的各個成員。

1.2.1 search()

"javascript".search(/script/i);

上面的代碼的返回值為4


如果search()的參數(shù)不是正則表達式,則首先會通過RegExp構造函數(shù)將它轉換成正則表達式,search()方法不支持全局檢索,因為它忽略正則表達式參數(shù)中的修飾符g。


1.2.2 match()

match()方法的唯一參數(shù)是一個正則表達式,返回的是一個由匹配結果組成的數(shù)組。如果該正則表達式設置了修飾符g,則返回的數(shù)組包含字符串中的所有匹配結果。

'1 plus 2 equals 3'.match(/\d+/g)  //返回["1","2","3"]

返回來的數(shù)組還帶有另外兩個屬性:index和input,分別表示包含發(fā)生匹配的字符位置和引用的正在檢索的字符串。


1.2.3 replace()

replace()方法用以執(zhí)行檢索與替換操作。其中第一個參數(shù)是一個正則表達式,第二個參數(shù)是要進行替換的字符串。


如果replace()的第一個參數(shù)是字符串而不是正則表達式,則replace()將直接搜索這個字符串,而不會像search()一樣首先通過RegExp()將它轉換為正則表達式。


replace方法的第二個參數(shù)可以使用美元符號$,用來指代所替換的內容。

$& 指代匹配的子字符串。  

$` 指代匹配結果前面的文本。  

$' 指代匹配結果后面的文本。  

$n 指代匹配成功的第n組內容,n是從1開始的自然數(shù)。  

$$ 指代美元符號$。

比如:

'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')  

// "world hello"

replace方法的第二個參數(shù)還可以是一個函數(shù),將每一個匹配內容替換為函數(shù)返回值。

'abca'.replace(/a/g,function(match){   

  return match.toUpperCase();   

});

// "AbcA"

replace()方法的第二個參數(shù)可以接受多個參數(shù)。第一個參數(shù)是捕捉到的內容,第二個參數(shù)是捕捉到的組匹配(有多少個組匹配,就有多少個對應的參數(shù))。


1.2.4 split()

split()方法用以將調用它的字符串拆分為一個子串組成的數(shù)組。

'123,456,789'.split(',')  //返回["123","456","789"]

split()方法的參數(shù)也可以是一個正則表達式。


1.3 RegExp對象

RegExp()構造函數(shù)帶有兩個字符串參數(shù),第二個參數(shù)是可選的,它指定正則表達式的修飾符(可傳入修飾符g、i、m或者它們的組合);第一個參數(shù)包含正則表達式的主體部分,也就是正則表達式直接量中兩條斜線之間的文本。

var regexp = new RegExp('\\d{5}','g')

上面的代碼表示會全局的查找5個數(shù)字。


1.3.1 RegExp對象的屬性

每個RegExp對象都包含5個屬性:

source    只讀字符串,包含正則表達式的文本

global    只讀布爾值,用以說明這個正則表達式是否帶有修飾符g

ignoreCase    只讀布爾值,用以說明正則表達式是否帶有修飾符i

multiline    只讀布爾值,用以說明正則表達式是否帶有修飾符m

lastIndex    可讀寫的整數(shù),如果匹配模式帶有g修飾符,這個屬性存儲在整個字符串中下一次檢索的開始位置。


1.3.2 RegExp的方法

RegExp對象定義了兩個用于執(zhí)行模式匹配操作的方法。


(1)exec()

正則對象的exec方法,可以返回匹配結果。如果發(fā)現(xiàn)匹配,就返回一個數(shù)組,成員是每一個匹配成功的子字符串,否則返回null。

/a|b|c/.exec('abc')  // ["a"]


/a|b|c/.exec('qwe')  // null


(2)test()

正則對象的test方法返回一個布爾值,表示當前模式是否能匹配參數(shù)字符串。

var s = /a/g;   

var a = 'baba';   

s.lastIndex   //0

s.test(a);   //true

  

s.lastIndex;   //2

s.test(a);  //true

注意:如果正則表達式帶有g修飾符,則每一次test方法都從上一次結束的位置開始向后匹配,也可以通過正則對象的lastIndex屬性指定開始搜索的位置。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號