需要指出的是,這裡只是總結了Regex的常用的且比較簡單的文法,而不是全部文法,在我看來,掌握了這些常用文法,已經足夠應對日常應用了。Regex不只是應用在ECMAScript中,在JAVA、.Net、Unix等也有相應應用,這篇文章則是以ECMAScript中的Regex為基礎總結的。
一、Regex基礎
1、一般字元:字母、數字、底線、漢字以及所有沒有特殊意義的字元,如ABC123。在匹配時,匹配與之相同的字元。
2、特殊字元:(需要時,使用反斜線“\”進行轉義)
字元 |
含義 |
字元 |
含義 |
字元 |
含義 |
字元 |
含義 |
\a |
響鈴符 = \x07 |
^ |
匹配字串的開始位置 |
\b |
匹配單詞的開始或結束 |
{n} |
匹配n次 |
\f |
換頁符 = \x0C |
$ |
匹配字串的結束位置 |
\B |
匹配不是單詞開始和結束的位置 |
{n,} |
匹配至少n次 |
\n |
分行符號 = \x0A |
() |
標記一個子運算式的開始和結束 |
\d |
匹配數字 |
{n,m} |
匹配n到m次 |
\r |
斷行符號符 = \x0D |
[] |
自訂字元組合匹配 |
\D |
匹配任意不是數位字元 |
[0-9] |
匹配0到9中任意一個數字 |
\t |
定位字元 = \x09 |
{} |
修飾匹配次數的符號 |
\s |
匹配任意空白字元 |
[f-m] |
匹配f到m中任意一個字母 |
\v |
垂直定位字元 = \x0B |
. |
匹配除分行符號外的字元 |
\S |
匹配任意非空白字元 |
|
|
\e |
ESC符 = \x1B |
? |
匹配0或1次 |
\w |
匹配字母或數字或底線或漢字 |
|
|
\xXX |
使用兩位十六進位表示形式,可與該編號的字元匹配 |
+ |
匹配1或多次 |
\W |
匹配任意不是字母、數字、底線和漢字的字元 |
|
|
\uXXXX |
用四位十六進位表示形式,可與該編號的字元匹配 |
* |
匹配0或多次 |
[^x] |
匹配除x外的所有字元 |
|
|
\x{XXXXXX} |
使用任意位十六進位表示形式,可與該編號的字元匹配 |
| |
左右兩邊運算式之間“或”關係 |
[^aeiou] |
匹配除aeiou外的所有字元 |
|
|
上面列舉的這些特殊字元,可以大致的分為:
(1)不便書寫字元:如響鈴符(\a)、換頁符(\f)、分行符號(\n)、斷行符號符(\r)、定位字元(\t)、ESC符(\e)
(2)十六進位字元:如兩位(\x02)、四位(\x012B)、任意位(\x{A34D1})
(3)表示位置字元:如字串開始(^)、字串結束($)、單詞開始和結束(\b)、單詞中間(\B)
(4)表示次數字元:如0或1次(?)、1或多次(+)、0或多次(*)、n次({n})、至少n次({n,})、n到m次({n,m})
(5)修飾字元:如修飾次數({})、自訂群組合匹配([])、子運算式(())
(6)反義字元:
(A)通過大小寫反義:如\b和\B、\d和\D、\s和\S、\w和\W
(B)通過[^]反義:如[^x]、[^aeiou]
(C)其它特例:如\n和.也構成反義
(7)範圍字元:如數字範圍([0-9])、字母範圍([f-m])
(8)邏輯字元:如表示或(|)
3、轉義
(1)使用反斜線“\”轉義單個字元
(2)使用“\Q...\E”轉義,將運算式中間出現的字元全部作為一般字元
(3)使用“\U...\E”轉義,將運算式中間出現的字元全部作為一般字元,並且將小寫字母轉換成大寫匹配
(4)使用“\L...\E”轉義,將運算式中間出現的字元全部作為一般字元,並且將大寫字母轉換為小寫匹配
4、貪婪模式與懶惰模式
如果Regex中含有次數字元時,一般情況下,會儘可能匹配更多的字元,比如用l*n來匹配linjisong的話,會匹配linjison,而不是 lin,這種模式也就是Regex的貪婪模式;相對應的,可以通過添加字元“?”來設定為懶惰模式,也即儘可能匹配更少字元。如*?表示重複0次或多次, 但儘可能少重複。
5、分組和反向引用
(1)用小括弧(())將運算式包含,可以使得運算式作為一個整體來處理,從而達到分組的目的。
(2)預設情況下,每個分組會自動擷取一個組號,按照左括弧的順序,從1向後編號。
(3)引擎在處理時,會將小括弧內部運算式匹配的內容儲存下來,以方便在匹配過程中或匹配結束後進一步處理,可以使用反斜線和組號來引用這個內容,如\1表示第一個分組匹配的文本。
(4)也可以自訂群組名,文法是(?<name>exp),這個時候反向引用時,還可以使用\k<name>。
(5)也可以不儲存匹配內容,也不分配組號,文法是(?:exp)。
(6)小括弧有一些其他特殊文法,這裡列舉幾種,不再深入討論:
分類 |
代碼/文法 |
說明 |
捕獲 |
(exp) |
匹配exp,並捕獲文本到自動命名的組裡 |
(?<name>exp) |
匹配exp,並捕獲文本到名稱為name的組裡,也可以寫成(?'name'exp) |
(?:exp) |
匹配exp,不捕獲匹配的文本,也不給此分組分配組號 |
零寬斷言 |
(?=exp) |
匹配exp前面的位置 |
(?<=exp) |
匹配exp後面的位置 |
(?!exp) |
匹配後面跟的不是exp的位置 |
(?<!exp) |
匹配前面不是exp的位置 |
注釋 |
(?#comment) |
這種類型的分組不對Regex的處理產生任何影響,用於提供注釋讓人閱讀 |
到此,對於理解常用的Regex已經足夠了,若想繼續學習Regex的,可以參考Regex30分鐘入門教程。下面再熟悉一下Javascript中的Regex實現。
二、Javascript中的Regex對象RegExp
1、建立Regex
(1)使用字面量:文法 var exp = /pattern/flags;
A、pattern是任何Regex
B、flags有三種:g表示全域模式、i表示忽略大小寫、m表示多行模式
(2)使用RegExp內建建構函式:文法 var exp = new RegExp(pattern, flags);
A、使用建構函式時,pattern和flags都是字串形式,所以對於逸出字元需要雙重轉義,例如:
字面量 |
建構函式 |
/\[bc\]at/ |
"\\[bc\\]at" |
/\.at/ |
"\\.at" |
/name\/age/ |
"name\\/age" |
/\d.\d{1,2}/ |
"\\d.\\d{1,2}" |
/\w\\helllo\\123/ |
"\\w\\\\hello\\\\123" |
說明:ECMAScript 3使用字面量時會共用一個RegExp執行個體,使用new RegExp(pattern,flags)會為每個Regex建立一個執行個體;ECMAScript 5規定每次都建立新執行個體。
2、執行個體屬性
(1)global:布爾值,表示是否設定了g標誌。
(2)ignoreCase:布爾值,表示是否設定了i標誌。
(3)multiline:布爾值,表示是否設定了m標誌。
(4)lastIndex:整數,表示開始搜尋下一次匹配項的字元位置,從0算起。
(5)source:字串,表示按照字面量形式建立的字串模式,即便執行個體使用建構函式建立,儲存的也是字面量形式的字串模式。
3、執行個體方法
(1)exec()方法
A、一個參數,即要應用模式的字串,返回第一個匹配項資訊的數組,沒有匹配時返回null。
B、返回的數組是Array執行個體,但還額外有input和index屬性,分別表示應用Regex的字串和匹配項在字串中的位置。
C、匹配時,在返回的數組中,第1項是與整個模式比對的字串,其他項是與模式中的分組匹配的字串(如果沒有分組,則返回數組只有1項)。
D、對於exec(),即使設定了g,每次返回的也是一個匹配項,不同的是,設定了g,多次調用exec的開始搜尋位置不同,沒有設定g,每次都從開始搜尋。
(2)test()方法
接受一個字串參數,匹配返回true,不匹配返回false。
三、執行個體分析
下面看一個出自PhoneGap源碼中用于格式化的Regex
複製代碼 代碼如下:var pattern = /(.*?)%(.)(.*)/;
var str = 'lin%%jisong';
var match = pattern.exec(str);
console.info(match.join(','));//lin%%jisong,lin,%,jisong
var pattern2 = /(.*)%(.)(.*)/;
var match2 = pattern2.exec(str);
console.info(match2.join(','));//lin%%jisong,lin%,j,isong
分析:這裡pattern和pattern2都包含三個分組,第2、3個分組相同,第2個分組(.)匹配任意一個非換行字元,第3個分組(.*)儘可能多(貪婪模式)的匹配任意非換行字元,pattern中的第1個分組(.*?)儘可能少(懶惰模式)的匹配任意非換行字元,而pattern2中的第1個分組(.*)則是儘可能多(貪婪模式)的匹配任意非換行字元了。因此在保證整個模式比對成功(從而需要保留一個%字元用於匹配Regex中的%)的前提下,pattern中第1個分組匹配成了lin,而pattern2中第1個分組匹配成了lin%,分析到這裡上例中的輸出也就不難理解了。