原文地址:http://blog.csdn.net/lxcnn/article/details/4268033正則表達式
1概述
正則表達式(Regular Expression)是一種匹配模式,描述的是一串文本的特徵。編程
正如天然語言中「高大」、「堅固」等詞語抽象出來描述事物特徵同樣,正則表達式就是字符的高度抽象,用來描述字符串的特徵。編程語言
正則表達式(如下簡稱正則,Regex)一般不獨立存在,各類編程語言和工具做爲宿主語言提供對正則的支持,並根據自身語言的特色,進行必定的剪裁或擴展。工具
正則入門很容易,有限的語法規則很容易掌握,可是目前正則的普及率並不高,主要是由於正則的流派衆多,各類宿主語言提供的文檔都過多的關注於自身的一些細節,而這些細節一般是初學者並不須要關注的。post
固然,若是想要深刻的瞭解正則表達式,這些細節又是必須被關注的,這是後話,讓咱們先從正則的基礎開始,進入正則表達式的世界。atom
2正則表達式基礎
2.1基本概念
2.1.1 字符串組成
對於字符串「a5」,是由兩個字符「a」、「5」以及三個位置組成的,這一點對於正則表達式的匹配原理理解很重要。spa
2.1.2 佔有字符和零寬度
正則表達式匹配過程當中,若是子表達式匹配到的是字符內容,而非位置,並被保存到最終的匹配結果中,那麼就認爲這個子表達式是佔有字符的;若是子表達式匹配的僅僅是位置,或者匹配的內容並不保存到最終的匹配結果中,那麼就認爲這個子表達式是零寬度的。.net
佔有字符仍是零寬度,是針對匹配的內容是否保存到最終的匹配結果中而言的。xml
佔有字符是互斥的,零寬度是非互斥的。也就是一個字符,同一時間只能由一個子表達式匹配,而一個位置,卻能夠同時由多個零寬度的子表達式匹配。blog
2.1.3 正則表達式構成
正則表達式由兩種字符構成。一種是在正則表達式中具體特殊意義的「元字符」,另外一種是普通的「文本字符」。
元字符能夠是一個字符,如「^」,也能夠是一個字符序列,如「\w」。
2.2元字符(Meta Character)
2.2.1 […] 字符組(Character Classes)
字符組能夠匹配[ ]中包含的任意一個字符。雖然能夠是任意一個,但只能是一個。
字符組支持由連字符「-」來表示一個範圍。當「-」先後構成範圍時,要求前面字符的碼位小於後面字符的碼位。
[^…] 排除型字符組。排除型字符組表示任意一個未列出的字符,一樣只能是一個。排除型字符組一樣支持由連字符「-」來表示一個範圍。
表達式 |
說明 |
[abc] |
表示「a」或「b」或「c」 |
[0-9] |
表示0~9中任意一個數字,等價於[0123456789] |
[\u4e00-\u9fa5] |
表示任意一個漢字 |
[^a1<] |
表示除「a」、「1」、「<」外的其它任意一個字符 |
[^a-z] |
表示除小寫字母外的任意一個字符 |
舉例:
「[0-9][0-9]」在匹配「Windows 2003」時,匹配成功,匹配的結果爲「20」。
「[^inW]」在匹配「Windows 2003」時,匹配成功,匹配的結果爲「d」。
2.2.2 常見字符範圍縮寫
對於一些經常使用的字符範圍,如數字等,因爲很是經常使用,即便使用[0-9]這樣的字符組仍顯得麻煩,因此定義了一些元字符,來表示常見的字符範圍。
表達式 |
說明 |
\d |
任意一個數字,至關於[0-9],即0~9 中的任意一個 |
\w |
任意一個字母或數字或下劃線,至關於[a-zA-Z0-9_] |
\s |
任意空白字符,至關於[ \r\n\f\t\v] |
\D |
任意一個非數字字符,\d取反,至關於[^0-9] |
\W |
\w取反,至關於[^a-zA-Z0-9_] |
\S |
任意非空白字符,\s取反,至關於[^ \r\n\f\t\v] |
舉例:
「\w\s\d」在匹配「Windows 2003」時,匹配成功,匹配的結果爲「s 2」。
2.2.3 . 小數點
小數點能夠匹配除「\n」之外的任意一個字符。若是要匹配包括「\n」在內的全部字符,通常用[\s\S],或者是用「.」加(?s)匹配模式來實現。
表達式 |
說明 |
. |
匹配除了換行符 \n 之外的任意一個字符 |
2.2.4 其它元字符
表達式 |
說明 |
^ |
匹配字符串開始的位置,不匹配任何字符 |
$ |
匹配字符串結束的位置,不匹配任何字符 |
\b |
匹配單詞邊界,不匹配任何字符 |
舉例:
「^a」在匹配「cba」時,匹配失敗,由於表達式要求開始位置後面是字符「a」,而「cba」顯然是不知足的。
「\d$」在匹配「123」時,匹配成功,匹配結果爲「3」,這個表達式要求匹配結尾處的數字,若是結尾處不是數字,如「123abc」,則是匹配失敗的。
2.2.5 轉義字符
一些不可見字符,或是在正則中具備特殊意義的元字符,如想匹配字符自己,須要用「\」對其進行轉義。
表達式 |
說明 |
\r,\n |
回車和換行 |
\\ |
匹配「\」自己 |
\^,$,\. |
分別匹配「^」、「$」和「.」 |
如下字符在匹配其自己時,一般須要進行轉義。在實際應用中,根據具體狀況,須要轉義的字符可能不止以下所列字符
. $ ^ { [ ( | ) * + ? \
2.2.6 量詞(Quantifier)
量詞表示一個子表達式能夠匹配的次數。量詞能夠用來修飾一個字符、字符組,或是用()括起來的子表達式。一些經常使用的量詞被定義成獨立的元字符。
表達式 |
說明 |
舉例 |
{m} |
表達式匹配m次 |
「\d{3}」至關於「\d\d\d 」 「(abc){2}」至關於「abcabc」 |
{m,n} |
表達式匹配最少m次,最多n次 |
「\d{2,3}」能夠匹配「12」或「321」等2到3位的數字 |
{m,} |
表達式至少匹配m次 |
「[a-z]{8,}」表示至少8位以上的字母 |
? |
表達式匹配0次或1次,至關於{0,1} |
「ab?」能夠匹配「a」或「ab」 |
* |
表達式匹配0次或任意屢次,至關於{0,} |
「<[^>]*>」中「[^>]*」表示0個或任意多個不是「>」的字符 |
+ |
表達式匹配1次或意屢次,至少1次,至關於{1,} |
「\d\s+\d」表示兩個數字中間,至少有一個以上的空白字符 |
注意:在不是動態生成的正則表達式中,不要出現「{1}」這樣的量詞,如「\w{1}」在結果上等價於「\w」,可是會下降匹配效率和可讀性,屬於多此一舉的作法。
2.2.7 分支結構(Alternation)
當一個字符串的某一子串具備多種可能時,採用分支結構來匹配,「|」表示多個子表達式之間「或」的關係,「|」是以()限定範圍的,若是在「|」的左右兩側沒有()來限定範圍,那麼它的做用範圍即爲「|」左右兩側總體。
表達式 |
說明 |
| |
多個子表達式之間取「或」的關係 |
舉例:
「^aa|b$」在匹配「cccb」時,是能夠匹配成功的,匹配的結果是「b」,由於這個表達式表示匹配「^aa」或「b」,而「b」,而「b」在匹配「cccb 」時是能夠匹配成功的。
「^(aa|b)$」在區配「cccb」時,是匹配失敗的,由於這個表達式表示在「開始」和「結束」位置之間只能是「aa」或「b」,而「cccb」顯然是不知足的。
3正則表達式進階
3.1捕獲組(Capture Group)
捕獲組就是把正則表達式中子表達式匹配的內容,保存到內存中以數字編號或手動命名的組裏,以供後面引用。
表達式 |
說明 |
(Expression) |
普通捕獲組,將子表達式Expression匹配的內容保存到以數字編號的組裏 |
(?<name> Expression) |
命名捕獲組,將子表達式Expression匹配的內容保存到以name命名的組裏 |
普通捕獲組(在不產生歧義的狀況下,簡稱捕獲組)是以數字進行編號的,編號規則是以「(」從左到右出現的順序,從1開始進行編號。一般狀況下,編號爲0的組表示整個表達式匹配的內容。
命名捕獲組能夠經過捕獲組名,而不是序號對捕獲內容進行引用,提供了更便捷的引用方式,不用關注捕獲組的序號,也不用擔憂表達式部分變動會致使引用錯誤的捕獲組。
3.2非捕獲組
一些表達式中,不得不使用( ),但又不須要保存( )中子表達式匹配的內容,這時能夠用非捕獲組來抵消使用( )帶來的反作用。
表達式 |
說明 |
(?:Expression) |
進行子表達式Expression的匹配,並將匹配內容保存到最終的整個表達式的區配結果中,但Expression匹配的內容不單獨保存到一個組內 |
3.3反向引用
捕獲組匹配的內容,能夠在正則表達式的外部程序中進行引用,也能夠在表達式中進行引用,表達式中引用的方式就是反向引用。
反向引用一般用來查找重複的子串,或是限定某一子串成對出現。
表達式 |
說明 |
\1,\2 |
對序號爲1和2的捕獲組的反向引用 |
\k<name> |
對命名爲name的捕獲組的反向引用 |
舉例:
「(a|b)\1」在匹配「abaa」時,匹配成功,匹配到的結果是「aa」。「(a|b)」在嘗試匹配時,雖然既能夠匹配「a」,也能夠匹配「b」,可是在進行反向引用時,對應()中匹配的內容已是固定的了。
3.4 環視(Look Around)
環視只進行子表達式的匹配,匹配內容不計入最終的匹配結果,是零寬度的。
環視按照方向劃分有順序和逆序兩種,按照是否匹配有確定和否認兩種,組合起來就有四種環視。環視至關於對所在位置加了一個附加條件。
表達式 |
說明 |
(?<=Expression) |
逆序確定環視,表示所在位置左側可以匹配Expression |
(?<!Expression) |
逆序否認環視,表示所在位置左側不能匹配Expression |
(?=Expression) |
順序確定環視,表示所在位置右側可以匹配Expression |
(?!Expression) |
順序否認環視,表示所在位置右側不能匹配Expression |
舉例:
「(?<=Windows )\d+」在匹配「Windows 2003」時,匹配成功,匹配結果爲「2003」。咱們知道「\d+」表示匹配一個以上的數字,而「(?<=Windows )」至關於一個附加條件,表示所在位置左側必須爲「Windows 」,它所匹配的內容並不計入匹配結果。一樣的正則在匹配「Office 2003」時,匹配失敗,由於這裏任意一串數字子串的左側都不是「Windows 」。
「(?!1)\d+」在匹配「123」時,匹配成功,匹配的結果爲「23」。「\d+」匹配一個以上數字,可是附加條件「(?!1)」要求所在位置右側不能是「1」,因此匹配成功的位置是「2」前面的位置。
3.5忽略優先和匹配優先
或者叫作正則表達式匹配的貪婪與非貪婪模式。
標準量詞修飾的子表達式,在可匹配可不匹配的狀況下,總會先嚐試進行匹配,稱這種方式爲匹配優先,或者貪婪模式。此前介紹的一些量詞,「{m}」、「{m,n}」、「{m,}」、「?」、「*」和「+」都是匹配優先的。
一些NFA正則引擎支持忽略優先量詞,也就是在標準量詞後加一個「?」,此時,在可匹配可不匹配的狀況下,總會先忽略匹配,只有在由忽略優先量詞修飾的子表達式,必須進行匹配才能使整個表達式匹配成功時,纔會進行匹配,稱這種方式爲忽略優先,或者非貪婪模式。忽略優先量詞包括「{m}?」、「{m,n}?」、「{m,}?」、「??」、「*?」和「+?」。
舉例:
源字符串:<div>aaa</div><div>bbb</div>
正則表達式1:<div>.*</div> 匹配結果:<div>aaa</div><div>bbb</div>
正則表達式2:<div>.*?</div> 匹配結果:<div>aaa</div>