學習正則表達式的你們,有沒有發現,一開始總是記不住語法。嗯,加深大家的印象的同時,我也是來找同道中人的。
先你要記住它的名字
正則表達式
regular expression
縮寫 regexp 、regex 、egrep。
正則表達式可以干嘛
數據驗證。
復雜的字符串搜尋、替換。
基于模式匹配從字符串中提取子字符串。
概述
正則表達式包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為“元字符”)。
若要匹配這些特殊字符,必須先轉義字符,即,在字符前面加反斜杠字符 \**。
例如,若要搜索 “+”文本字符,可使用表達式 \+。
但是大多數 特殊字符 在中括號表達式內出現時失去本來的意義,并恢復為普通字符。
構造函數(四種寫法)
JavaScript
var regex = new RegExp('xyz', 'i');
var regex = new RegExp(/xyz/i);
var regex = /xyz/i;
// ES6的寫法。ES5在個參數是正則時,不允許此時使用第二個參數,會報錯。
// 返回的正則表達式會忽略原有的正則表達式的修飾符,只使用新指定的修飾符。
// 下面代碼返回”i”。
new RegExp(/abc/ig, 'i').flags
用于模式匹配的String方法
String.search()
參數:要搜索的子字符串,或者一個正則表達式。
返回:個與參數匹配的子串的起始位置,如果找不到,返回-1。
說明:不支持全局搜索,如果參數是字符串,會先通過RegExp構造函數轉換成正則表達式。
String.replace()
作用:查找并替換字符串。
個參數:字符串或正則表達式,
第二個參數:要進行替換的字符串,也可以是函數。
用法:
替換文本中的$字符有特殊含義:
JavaScript
$1、$2、...、$99 與 regexp 中的第 1 到第 99 個子表達式相匹配的文本。
$& 與 regexp 相匹配的子串。
$` 位于匹配子串左側的文本。
$' 位于匹配子串右側的文本。
$$ 普通字符$。
如:
JavaScript
'abc'.replace(/b/g, "{$$$`$&$'}")
// 結果為 "a{$abc}c",即把b換成了{$abc}
String.match()
參數:要搜索的子字符串,或者一個正則表達式。
返回:一個由匹配結果組成的數組。
非全局檢索:如果沒有找到任何匹配的文本返回null;否則數組的個元素是匹配的字符串,剩下的是小括號中的子表達式,即a[n]中存放的是$n的內容。非全局檢索返回三個屬性:length 屬性;index 屬性聲明的是匹配文本的個字符的位置;input 屬性則存放的是被檢索的字符串 string。
全局檢索:設置標志g則返回所有匹配子字符串,即不提供與子表達式相關的信息。沒有 index 屬性或 input 屬性。

String.split()
作用:把一個字符串分割成字符串數組。
參數:正則表達式或字符串。
返回:子串組成的數組。
RegExp的方法
RegExpObject.exec()
參數:字符串。
返回:
非全局檢索:與String.macth()非全局檢索相同,返回一個數組或null。
全局檢索:盡管是全局匹配的正則表達式,但是exec方法只對指定的字符串進行一次匹配。但是可以反復調用來實現全局檢索。在 RegExpObject 的lastIndex 屬性指定的字符處開始檢索字符串;匹配后,將更新lastIndex為匹配文本的后一個字符的下一個位置;再也找不到匹配的文本時,將返回null,并把 lastIndex 屬性重置為 0。
如:
exec_g
RegExpObject.test()
參數:字符串。
返回:true或false。
RegExpObject.toString()
返回:字符串
字符
| 指示在兩個或多個項之間進行選擇。類似js中的或,又稱分支條件。
/ 正則表達式模式的開始或結尾。
\ 反斜杠字符,用來轉義。
- 連字符 當且僅當在字符組[]的內部表示一個范圍,比如[A-Z]就是表示范圍從A到Z;如果需要在字符組里面表示普通字符-,放在字符組的開頭即可。
. 匹配除換行符 \n 之外的任何單個字符。
\d 等價[0-9],匹配0到9字符。
\D 等價[^0-9],與\d相反。
\w 與以下任意字符匹配:A-Z、a-z、0-9 和下劃線,等價于 [A-Za-z0-9]。
\W 與\w相反,即 [^A-Za-z0-9]
限定符(量詞字符)
顯示限定符位于大括號 {} 中,并包含指示出現次數上下限的數值;*+? 這三個字符屬于單字符限定符:
{n} 正好匹配 n 次。
{n,} 至少匹配 n 次。
{n,m} 匹配至少 n 次,至多 m 次。
* 等價{0,}
+ 等價{1,}
? 等價{0,1}
注意:
顯示限定符中,逗號和數字之間不能有空格,否則返回null!
貪婪量詞*和+:javascript默認是貪婪匹配,也就是說匹配重復字符是盡可能多地匹配。
惰性(少重復匹配)量詞?:當進行非貪婪匹配,只需要在待匹配的字符后面跟隨一個?即可。
JavaScript
var reg = /a+/;
var reg2 = /a+?/;
var str = 'aaab';
str.match(reg); // ["aaa"]
str.match(reg2); // ["a"]
定位點(錨字符、邊界)
^ 匹配開始的位置。將 ^ 用作括號[]表達式中的個字符,則會對字符集求反。
$ 匹配結尾的位置。
\b 與一個字邊界匹配,如er\b 與“never”中的“er”匹配,但與“verb”中的“er”不匹配。
\B 非邊界字匹配。
標記
中括號[] 字符組;標記括號表達式的開始和結尾,起到的作用是匹配這個或者匹配那個。
[...] 匹配方括號內任意字符。很多字符在[]都會失去本來的意義:[^...]匹配不在方括號內的任意字符;[?.]匹配普通的問號和點號。
但是不要濫用字符組這個失去意義的特性,比如不要使用[.]來代替\:轉義點號,因為需要付出處理字符組的代價。
大括號{} 標記限定符表達式的開始和結尾。
小括號() 標記子表達式的開始和結尾,主要作用是分組,對內容進行區分。
(模式) 可以記住和這個模式匹配的匹配項(捕獲分組)。不要濫用括號,如果不需要保存子表達式,可使用非捕獲型括號(?:)來進行性能優化。
(?:模式) 與模式 匹配,但不保存匹配項(非捕獲分組)。
(?=模式) 零寬正向先行斷言,要求匹配與模式 匹配的搜索字符串。 找到一個匹配項后,將在匹配文本之前開始搜索下一個匹配項;但不會保存匹配項。
(?!模式) 零寬負向先行斷言,要求匹配與模式 不匹配的搜索字符串。 找到一個匹配項后,將在匹配文本之前開始搜索下一個匹配項;但不會保存匹配項。
有點暈?
好,換個說法。。。
先行斷言(?=模式):x只有在y前面才匹配,必須寫成/x(?=y)/。 解釋:找一個x,那個x的后面有y。
先行否定斷言(?!模式): x只有不在y前面才匹配,必須寫成/x(?!y)/。 解釋:找一個x,那個x的后面沒有y。
穩住,又來了兩個斷言,來自ES7提案:
后行斷言(?<=模式):與”先行斷言”相反, x只有在y后面才匹配,必須寫成/(?<=y)x/。解釋:找一個x,那個x的前面要有y。
后行否定斷言(?<!模式): 與”先行否定斷言“相反,x只有不在y后面才匹配,必須寫成/(?<!y)x/。 解釋:找一個x,那個x的前面沒有y。
可以看出,后行斷言先匹配/(?<=y)x/的x,然后再回到左邊,匹配y的部分,即先右后左”的執行順序。
零寬負向先行斷言的例子:
JavaScript
var str=`<div class="o2">
<div class="o2_team">
<img src="img/logo.jpg" />
</div>
</div>`;
// <(?!img) 表示找一個左尖括號<,而且左尖括號<的后面沒有img字符;
// (?:.|\r|\n)*? 表示匹配左右尖括號<>里面的.或\r或\n,而且匹配次數為*?;(?:)不保存匹配項,提高性能;
// *后面加個? 表示非貪婪匹配。
var reg = /<(?!img)(?:.|\r|\n)*?>/gi;
str.match(reg);
// 返回結果 ["<div class="o2">", "<div class="o2_team">", "</div>", "</div>"]
反向引用:主要作用是給分組加上標識符\n。
\n 表示引用字符,與第n個子表達式次匹配的字符相匹配。
反向引用的例子,給MikeMike字符后加個單引號:
JavaScript
var reg = /(Mike)(\1)(s)/;
var str = "MikeMikes";
console.log(str.replace(reg,"$1$2'$3"));
// 返回結果 MikeMike's
非打印字符
\s 任何空白字符。即[ \f\n\r\t\v]
\S 任何非空白字符。
\t Tab 字符(\u0009)。
\n 換行符(\u000A)
\v 垂直制表符(\u000B)。
\f 換頁符(\u000C)
\r 回車符(\u000D)。
注意:\n和\r一起使用,即 /[\r\n]/g來匹配換行,因為unix擴展的系統以\n標志結尾,window以\r\n標志結尾。
其他
\cx 匹配 x 指示的控制字符,要求x 的值必須在 A-Z 或 a-z 范圍內。
\xn 匹配n,n 是一個十六進制轉義碼,兩位數長。
\un 匹配 n,其中n 是以四位十六進制數表示的 Unicode 字符。
\nm 或 \n 先嘗試反向引用,不可則再嘗試標識為一個八進制轉義碼。
\nml 當n 是八進制數字 (0-3),m 和 l 是八進制數字 (0-7) 時,匹配八進制轉義碼 nml。
修飾符
i 執行不區分大小寫的匹配。
g 執行一個全局匹配,簡而言之,即找到所有的匹配,而不是在找到個之后就停止。
m 多行匹配模式,^匹配一行的開頭和字符串的開頭,$匹配行的結束和字符串的結束。
ES6新增u和y修飾符:
u修飾符
含義為“Unicode模式”,用來正確處理大于\uFFFF的Unicode字符。也就是說,會正確處理四個字節的UTF-16編碼。
JavaScript
// 加u修飾符以后,ES6就會識別\uD83D\uDC2A為一個字符,返回false。
/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
y修飾符
與g修飾符都是全局匹配,不同之處在于:lastIndex屬性指定每次搜索的開始位置,g修飾符從這個位置開始向后搜索,直到發現匹配為止;但是y修飾符要求必須在lastIndex指定的位置發現匹配,即y修飾符確保匹配必須從剩余的個位置開始,這也是“粘連”的涵義。
JavaScript
/b/y.exec('aba') // null
/b/.exec('aba') // ["b"]
優先順序:
\ 轉義符
(), (?:), (?=), [] 括號和中括號
*、+、?、{n}、{n,}、{n,m} 限定符
任何元字符^、$、\ 定位點和序列
| 替換
關于引擎
JS 是 NFA 引擎。
NFA 引擎的特點:
以貪婪方式進行,盡可能匹配更多字符。
急于邀功請賞,所以左子正則式優先匹配成功,因此偶爾會錯過佳匹配結果(多選條件分支的情況)。
JavaScript
'nfa not'.match(/nfa|nfa not/)
// 返回["nfa"]
回溯(backtracking),導致速度慢。
舉個貪婪與回溯結合的例子:
JavaScript
"AB01CD23CD45CEff".match('AB.*CD')
// 返回 ["AB01CD23CD"]
匹配順序如圖所示:

深圳網站建設www.ykfic.cn