## 正則表達(dá)式
正則表達(dá)式(regular expression)是一個(gè)描述字符模式的對(duì)象。JavaScript的RegExp類表示正則表達(dá)式,String和RegExp都定義了方法。
**1.1 正則表達(dá)式的定義**
正則表達(dá)式有兩種方法定義:
- 一種是使用正則表達(dá)式直接量,將其包含在一對(duì)斜杠(/)之間的字符。
```
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)方括號(hào)就組成了字符類(character class)。一個(gè)字符類可以匹配它所包含的任意字符。比如:/[abc]/就和字母“a”、“b”、“c”中的任意一個(gè)都匹配。
我們還可以通過“^”符號(hào)來定義否定字符類,它匹配所有不包含括號(hào)內(nèi)的字符。定義否定字符類時(shí),將一個(gè)“^”符號(hào)作為左方括號(hào)內(nèi)的第一個(gè)字符。比如: /[^abc]/ 匹配的是“a”、“b”、“c”之外的所有字符?!?
字符類還可以使用連字符來表示字符范圍。比如要匹配拉丁字母表中的小寫字母,可以使用 /[a-z]/ ,要匹配拉丁字母表中的任何字母和數(shù)字,則使用 /[a-zA-Z0-9]/ 。
注意:字符類的連字符必須在頭尾兩個(gè)字符中間,才有特殊含義,否則就是字面含義。比如,[-9]就表示匹配連字符和9,而不是匹配0到9。
正則表達(dá)式的字符類:
```
[...] 方括號(hào)內(nèi)的任意字符
[^...]不在方括號(hào)內(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] 退格直接量
```
注意:在方括號(hào)之內(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è)字符,因此它們?cè)试S什么都不匹配。比如:正則表達(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è)問號(hào)即可:“??”、“+?”、“*?”或“{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)匹配,就會(huì)忽略右邊的匹配項(xiàng),即使它產(chǎn)生更好的匹配。比如:當(dāng)正在表達(dá)式/a|ab/匹配字符串“ab”時(shí),它只能匹配第一個(gè)字符。
圓括號(hào)“()”可以把單獨(dú)的項(xiàng)組合成子表達(dá)式。
帶圓括號(hào)的表達(dá)式的另一個(gè)用途是允許在同一正則表達(dá)式的后部引用前面的子表達(dá)式,這是通過在字符“\”后加一位或多位數(shù)字來實(shí)現(xiàn)的,這個(gè)數(shù)字指定了帶圓括號(hào)的子表達(dá)式在正則表達(dá)式中的位置。比如:\1引用的是第一個(gè)帶圓括號(hào)的子表達(dá)式,\3引用的是第三個(gè)帶圓括號(hào)的子表達(dá)式。
```
/(.)b(.)\1b\2/.test('abcabc') //true
```
上面的代碼中,\1表示第一個(gè)括號(hào)匹配的內(nèi)容,即第一個(gè)(.),匹配的是“a”;\2表示第二個(gè)括號(hào)(.),匹配的是“b”。
注意:因?yàn)樽颖磉_(dá)式可以嵌套另一個(gè)子表達(dá)式,所以引用的位置是參與計(jì)數(shù)的左括號(hào)的位置。比如:(s(ss)),\2表示的是(ss)。
對(duì)正則表達(dá)式中前一個(gè)子表達(dá)式的引用,并不是指對(duì)子表達(dá)式模式的引用,而指的是那個(gè)模式相匹配的文本的引用。
```
/(a|b)c\1/.test('aca') //true
/(a|b)c\1/.test('acb') //false
```
上面的代碼中,由于(a|b)匹配的是a,所以\1所對(duì)應(yīng)的也應(yīng)該是a。
正則表達(dá)式的選擇、分組和引用字符
```
| 選擇,匹配的是該符號(hào)左邊的子表達(dá)式或右邊的子表達(dá)式
(...) 組合,將幾個(gè)項(xiàng)組合為一個(gè)單位,這個(gè)單位可通過“*”、“+”、“?”和“|”等符號(hào)加以修飾,而且可以記住和這個(gè)組合相匹配的字符串以供此后的引用使用。
(?...) 只組合,把項(xiàng)組合到一個(gè)單位,但不記憶與該組相匹配的字符
\n 和第n個(gè)分組第一次匹配的字符相匹配,組是圓括號(hào)中的子表達(dá)式(也有可能是嵌套的),組索引是從左到右的左括號(hào)數(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á)式的修飾符,用以說明高級(jí)匹配模式的規(guī)則。修飾符是放在“/”符號(hào)之外的,也就是說,它們不是出現(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()**
按照給定的正則表達(dá)式進(jìn)行搜索,返回一個(gè)整數(shù),表示第一個(gè)與之匹配的字符串的起始位置,如果找不到匹配的子串,將返回-1。
```
"javascript".search(/script/i);
```
上面的代碼的返回值為4
如果search()的參數(shù)不是正則表達(dá)式,則首先會(huì)通過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è)字符串,而不會(huì)像search()一樣首先通過RegExp()將它轉(zhuǎn)換為正則表達(dá)式。
replace方法的第二個(gè)參數(shù)可以使用美元符號(hào)$,用來指代所替換的內(nèi)容。
$& 指代匹配的子字符串。
```
$` 指代匹配結(jié)果前面的文本。
$' 指代匹配結(jié)果后面的文本。
$n 指代匹配成功的第n組內(nèi)容,n是從1開始的自然數(shù)。
$$ 指代美元符號(hào)$。
```
比如:
```
'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è)對(duì)應(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對(duì)象**
RegExp()構(gòu)造函數(shù)帶有兩個(gè)字符串參數(shù),第二個(gè)參數(shù)是可選的,它指定正則表達(dá)式的修飾符(可傳入修飾符g、i、m或者它們的組合);第一個(gè)參數(shù)包含正則表達(dá)式的主體部分,也就是正則表達(dá)式直接量中兩條斜線之間的文本。
```
var regexp = new RegExp('\\d{5}','g')
```
上面的代碼表示會(huì)全局的查找5個(gè)數(shù)字。
**1.3.1 RegExp對(duì)象的屬性**
每個(gè)RegExp對(duì)象都包含5個(gè)屬性:
- source 只讀字符串,包含正則表達(dá)式的文本
- global 只讀布爾值,用以說明這個(gè)正則表達(dá)式是否帶有修飾符g
- ignoreCase 只讀布爾值,用以說明正則表達(dá)式是否帶有修飾符i
- multiline 只讀布爾值,用以說明正則表達(dá)式是否帶有修飾符m
- lastIndex 可讀寫的整數(shù),如果匹配模式帶有g(shù)修飾符,這個(gè)屬性存儲(chǔ)在整個(gè)字符串中下一次檢索的開始位置。
**1.3.2 RegExp的方法**
RegExp對(duì)象定義了兩個(gè)用于執(zhí)行模式匹配操作的方法。
**(1)exec()**
正則對(duì)象的exec方法,可以返回匹配結(jié)果。如果發(fā)現(xiàn)匹配,就返回一個(gè)數(shù)組,成員是每一個(gè)匹配成功的子字符串,否則返回null。
```
/a|b|c/.exec('abc') // ["a"]
/a|b|c/.exec('qwe') // null
```
**(2)test()**
正則對(duì)象的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é)束的位置開始向后匹配,也可以通過正則對(duì)象的lastIndex屬性指定開始搜索的位置。
- 前言
- JavaScript簡(jiǎn)介
- 基本概念
- 語法
- 數(shù)據(jù)類型
- 運(yùn)算符
- 表達(dá)式
- 語句
- 對(duì)象
- 數(shù)組
- 函數(shù)
- 引用類型(對(duì)象)
- Object對(duì)象
- Array對(duì)象
- Date對(duì)象
- RegExp對(duì)象
- 基本包裝類型(Boolean、Number、String)
- 單體內(nèi)置對(duì)象(Global、Math)
- console對(duì)象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達(dá)式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應(yīng)用
- 客戶端存儲(chǔ)(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測(cè)設(shè)備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向?qū)ο蟮某绦蛟O(shè)計(jì)
- 概述
- this關(guān)鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯(cuò)誤處理機(jī)制
- JavaScript開發(fā)技巧合集
- 編程風(fēng)格
- 垃圾回收機(jī)制
