JavaScript學(xué)習(xí)筆記整理(13):正則表達(dá)式

2018-06-19 13:51 更新

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


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

var pattern = /s$/;

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

var pattern = new RegExp('s');

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

正則表達(dá)式的字符類:

[...]  方括號內(nèi)的任意字符

[^...]不在方括號內(nèi)的任意字符

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

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

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

\s  任何Unicode空白符

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

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

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

[\b]  退格直接量

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

正則表達(dá)式的重復(fù)字符語法:

{n,m}  匹配前一項(xiàng)至少n次,至多m次

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

{n}    匹配前一項(xiàng)n次

?      匹配前一項(xiàng)0次或者1次,等價(jià)于{0,1}

+      匹配前一項(xiàng)1次或多次,等價(jià)于{1,}

*      匹配前一項(xiàng)0次或多次,等價(jià)于{0,}

注意:在使用“*”和“?”時(shí),由于這些字符可能匹配0個(gè)字符,因此它們允許什么都不匹配。比如:正則表達(dá)式/a*/實(shí)際上與字符串“bbb”匹配,因?yàn)檫@個(gè)字符串含有0個(gè)a。

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

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

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

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


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

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

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

圓括號“()”可以把單獨(dú)的項(xiàng)組合成子表達(dá)式。

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

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

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

注意:因?yàn)樽颖磉_(dá)式可以嵌套另一個(gè)子表達(dá)式,所以引用的位置是參與計(jì)數(shù)的左括號的位置。比如:(s(ss)),\2表示的是(ss)。

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

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

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

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

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

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

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

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

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


1.1.6 指定匹配位置

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


正則表達(dá)式中的錨字符:

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

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

\b   匹配一個(gè)單詞的邊界

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

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

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


1.1.7  修飾符

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


在JavaScript中,支持三個(gè)修飾符:

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

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

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

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

/test/ig


1.2 用于模式匹配的String方法

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

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

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

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

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

1.2.1 search()

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

上面的代碼的返回值為4


如果search()的參數(shù)不是正則表達(dá)式,則首先會通過RegExp構(gòu)造函數(shù)將它轉(zhuǎn)換成正則表達(dá)式,search()方法不支持全局檢索,因?yàn)樗雎哉齽t表達(dá)式參數(shù)中的修飾符g。


1.2.2 match()

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

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

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


1.2.3 replace()

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


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


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

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

$` 指代匹配結(jié)果前面的文本。  

$' 指代匹配結(jié)果后面的文本。  

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

$$ 指代美元符號$。

比如:

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

// "world hello"

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

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

  return match.toUpperCase();   

});

// "AbcA"

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


1.2.4 split()

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

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

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


1.3 RegExp對象

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

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

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


1.3.1 RegExp對象的屬性

每個(gè)RegExp對象都包含5個(gè)屬性:

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

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

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

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

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


1.3.2 RegExp的方法

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


(1)exec()

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

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


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


(2)test()

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

var s = /a/g;   

var a = 'baba';   

s.lastIndex   //0

s.test(a);   //true

  

s.lastIndex;   //2

s.test(a);  //true

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


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號