正則表達式--anton菜鳥筆記

正則表達式

正則表達式(Regular Expression)是一種文本模式,包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱爲"元字符")。html

正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。git

正則表達式是煩瑣的,但它是強大的,學會以後的應用會讓你除了提升效率外,會給你帶來絕對的成就感。只要認真閱讀本教程,加上應用的時候進行必定的參考,掌握正則表達式不是問題。正則表達式

許多程序設計語言都支持利用正則表達式進行字符串操做。算法

 

正則表達式的使用,能夠經過簡單的辦法來實現強大的功能。下面先給出一個簡單的示例:express

    • ^ 爲匹配輸入字符串的開始位置。數組

    • [0-9]+匹配多個數字, [0-9] 匹配單個數字,+ 匹配一個或者多個。緩存

    • abc$匹配字母 abc 並以 abc 結尾,網絡

    • $ 爲匹配輸入字符串的結束位置。app

實例

匹配以數字開頭,並以 abc 結尾的字符串。:編輯器

var str = "123abc";
var patt1
= /^[0-9]+abc$/;
document.write(str.match(patt1));

結果:123ab

爲何使用正則表達式?

典型的搜索和替換操做要求您提供與預期的搜索結果匹配的確切文本。雖然這種技術對於對靜態文本執行簡單搜索和替換任務可能已經足夠了,但它缺少靈活性,若採用這種方法搜索動態文本,即便不是不可能,至少也會變得很困難。

經過使用正則表達式,能夠:

    • 測試字符串內的模式。
      例如,能夠測試輸入字符串,以查看字符串內是否出現電話號碼模式或信用卡號碼模式。這稱爲數據驗證。
    • 替換文本。
      可使用正則表達式來識別文檔中的特定文本,徹底刪除該文本或者用其餘文本替換它。
    • 基於模式匹配從字符串中提取子字符串。
      能夠查找文檔內或輸入域內特定的文本。

例如,您可能須要搜索整個網站,刪除過期的材料,以及替換某些 HTML 格式標記。在這種狀況下,可使用正則表達式來肯定在每一個文件中是否出現該材料或該 HTML 格式標記。此過程將受影響的文件列表縮小到包含須要刪除或更改的材料的那些文件。而後可使用正則表達式來刪除過期的材料。最後,可使用正則表達式來搜索和替換標記。


發展歷史

正則表達式的"祖先"能夠一直上溯至對人類神經系統如何工做的早期研究。Warren McCulloch 和 Walter Pitts 這兩位神經生理學家研究出一種數學方式來描述這些神經網絡。

1956 年, 一位叫 Stephen Kleene 的數學家在 McCulloch 和 Pitts 早期工做的基礎上,發表了一篇標題爲"神經網事件的表示法"的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱爲"正則集的代數"的表達式,所以採用"正則表達式"這個術語。

隨後,發現能夠將這一工做應用於使用 Ken Thompson 的計算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要發明人。正則表達式的第一個實用應用程序就是 Unix 中的 qed 編輯器。

如他們所說,剩下的就是衆所周知的歷史了。從那時起直至如今正則表達式都是基於文本的編輯器和搜索工具中的一個重要部分。


應用領域

目前,正則表達式已經在不少軟件中獲得普遍的應用,包括 *nix(Linux, Unix等)、HP 等操做系統,PHP、C#、Java 等開發環境,以及不少的應用軟件中,均可以看到正則表達式的影子。

 
 
 
語法
 

 

正則表達式(regular expression)描述了一種字符串匹配的模式(pattern),能夠用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等。

 

例如:

 

  • runoo+b,能夠匹配 runoob、runooob、runoooooob 等,+ 號表明前面的字符必須至少出現一次(1次或屢次)。

  • runoo*b,能夠匹配 runob、runoob、runoooooob 等,* 號表明字符能夠不出現,也能夠出現一次或者屢次(0次、或1次、或屢次)。

  • colou?r 能夠匹配 color 或者 colour,? 問號表明前面的字符最多隻能夠出現一次(0次、或1次)。

 

構造正則表達式的方法和建立數學表達式的方法同樣。也就是用多種元字符與運算符能夠將小的表達式結合在一塊兒來建立更大的表達式。正則表達式的組件能夠是單個的字符、字符集合、字符範圍、字符間的選擇或者全部這些組件的任意組合。

 

正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱爲"元字符")組成的文字模式。模式描述在搜索文本時要匹配的一個或多個字符串。正則表達式做爲一個模板,將某個字符模式與所搜索的字符串進行匹配。

 


 

普通字符

 

普通字符包括沒有顯式指定爲元字符的全部可打印和不可打印字符。這包括全部大寫和小寫字母、全部數字、全部標點符號和一些其餘符號。

 


 

非打印字符

 

非打印字符也能夠是正則表達式的組成部分。下表列出了表示非打印字符的轉義序列:

 

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。不然,將 c 視爲一個原義的 'c' 字符。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。注意 Unicode 正則表達式會匹配全角空格符。
\S 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。

 


 

特殊字符

 

所謂特殊字符,就是一些有特殊含義的字符,如上面說的 runoo*b 中的 *,簡單的說就是表示任何字符串的意思。若是要查找字符串中的 * 符號,則須要對 * 進行轉義,即在其前加一個 \: runo\*ob 匹配 runo*ob。

 

許多元字符要求在試圖匹配它們時特別對待。若要匹配這些特殊字符,必須首先使字符"轉義",即,將反斜槓字符\ 放在它們前面。下表列出了正則表達式中的特殊字符:

 

特別字符 描述
$ 匹配輸入字符串的結尾位置。若是設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符自己,請使用 \$。
( ) 標記一個子表達式的開始和結束位置。子表達式能夠獲取供之後使用。要匹配這些字符,請使用 \( 和 \)。
* 匹配前面的子表達式零次或屢次。要匹配 * 字符,請使用 \*。
+ 匹配前面的子表達式一次或屢次。要匹配 + 字符,請使用 \+。
. 匹配除換行符 \n 以外的任何單字符。要匹配 . ,請使用 \. 。
[ 標記一箇中括號表達式的開始。要匹配 [,請使用 \[。
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。
\ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符自己,請使用 \^。
{ 標記限定符表達式的開始。要匹配 {,請使用 \{。
| 指明兩項之間的一個選擇。要匹配 |,請使用 \|。

 


 

限定符

 

限定符用來指定正則表達式的一個給定組件必需要出現多少次才能知足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6種。

 

正則表達式的限定符有:

 

字符 描述
* 匹配前面的子表達式零次或屢次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表達式一次或屢次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
? 匹配前面的子表達式零次或一次。例如,"do(es)?" 能夠匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等價於 {0,1}。
{n} n 是一個非負整數。匹配肯定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',可是能匹配 "food" 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的全部 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。
{n,m} m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。

 

因爲章節編號在大的輸入文檔中會極可能超過九,因此您須要一種方式來處理兩位或三位章節編號。限定符給您這種能力。下面的正則表達式匹配編號爲任何位數的章節標題:

 

/Chapter [1-9][0-9]*/

 

請注意,限定符出如今範圍表達式以後。所以,它應用於整個範圍表達式,在本例中,只指定從 0 到 9 的數字(包括 0 和 9)。

 

這裏不使用 + 限定符,由於在第二個位置或後面的位置不必定須要有一個數字。也不使用 ? 字符,由於使用 ? 會將章節編號限制到只有兩位數。您須要至少匹配 Chapter 和空格字符後面的一個數字。

 

若是您知道章節編號被限制爲只有 99 章,可使用下面的表達式來至少指定一位但至多兩位數字。

 

/Chapter [0-9]{1,2}/

 

上面的表達式的缺點是,大於 99 的章節編號仍只匹配開頭兩位數字。另外一個缺點是 Chapter 0 也將匹配。只匹配兩位數字的更好的表達式以下:

 

/Chapter [1-9][0-9]?/

 

 

/Chapter [1-9][0-9]{0,1}/

 

*、+限定符都是貪婪的,由於它們會盡量多的匹配文字,只有在它們的後面加上一個?就能夠實現非貪婪或最小匹配。

 

例如,您可能搜索 HTML 文檔,以查找括在 H1 標記內的章節標題。該文本在您的文檔中以下:

 

<H1>Chapter 1 - 介紹正則表達式</H1>

 

貪婪:下面的表達式匹配從開始小於符號 (<) 到關閉 H1 標記的大於符號 (>) 之間的全部內容。

 

/<.*>/

 

非貪婪:若是您只須要匹配開始和結束 H1 標籤,下面的非貪婪表達式只匹配 <H1>。

 

/<.*?>/

 

若是隻想匹配開始的 H1 標籤,表達式則是:

 

/<\w+?>/

 

經過在 *、+ 或 ? 限定符以後放置 ?,該表達式從"貪心"表達式轉換爲"非貪心"表達式或者最小匹配。

 


 

定位符

 

定位符使您可以將正則表達式固定到行首或行尾。它們還使您可以建立這樣的正則表達式,這些正則表達式出如今一個單詞內、在一個單詞的開頭或者一個單詞的結尾。

 

定位符用來描述字符串或單詞的邊界,^ 和 $ 分別指字符串的開始與結束,\b 描述單詞的前或後邊界,\B 表示非單詞邊界。

 

正則表達式的定位符有:

 

字符 描述
^ 匹配輸入字符串開始的位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 還會與 \n 或 \r 以後的位置匹配。
$ 匹配輸入字符串結尾的位置。若是設置了 RegExp 對象的 Multiline 屬性,$ 還會與 \n 或 \r 以前的位置匹配。
\b 匹配一個字邊界,即字與空格間的位置。
\B 非字邊界匹配。

 

注意:不能將限定符與定位符一塊兒使用。因爲在緊靠換行或者字邊界的前面或後面不能有一個以上位置,所以不容許諸如 ^* 之類的表達式。

 

若要匹配一行文本開始處的文本,請在正則表達式的開始使用 ^ 字符。不要將 ^ 的這種用法與中括號表達式內的用法混淆。

 

若要匹配一行文本的結束處的文本,請在正則表達式的結束處使用 $ 字符。

 

若要在搜索章節標題時使用定位點,下面的正則表達式匹配一個章節標題,該標題只包含兩個尾隨數字,而且出如今行首:

 

/^Chapter [1-9][0-9]{0,1}/

 

真正的章節標題不只出現行的開始處,並且它仍是該行中僅有的文本。它即出如今行首又出如今同一行的結尾。下面的表達式能確保指定的匹配只匹配章節而不匹配交叉引用。經過建立只匹配一行文本的開始和結尾的正則表達式,就可作到這一點。

 

/^Chapter [1-9][0-9]{0,1}$/

 

匹配字邊界稍有不一樣,但向正則表達式添加了很重要的能力。字邊界是單詞和空格之間的位置。非字邊界是任何其餘位置。下面的表達式匹配單詞 Chapter 的開頭三個字符,由於這三個字符出如今字邊界後面:

 

/\bCha/

 

\b 字符的位置是很是重要的。若是它位於要匹配的字符串的開始,它在單詞的開始處查找匹配項。若是它位於字符串的結尾,它在單詞的結尾處查找匹配項。例如,下面的表達式匹配單詞 Chapter 中的字符串 ter,由於它出如今字邊界的前面:

 

/ter\b/

 

下面的表達式匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt:

 

/\Bapt/

 

字符串 apt 出如今單詞 Chapter 中的非字邊界處,但出如今單詞 aptitude 中的字邊界處。對於 \B 非字邊界運算符,位置並不重要,由於匹配不關心到底是單詞的開頭仍是結尾。

 


 

選擇

 

用圓括號將全部選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個反作用,使相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種反作用。

 

其中 ?: 是非捕獲元之一,還有兩個非捕獲元是 ?= 和 ?!,這兩個還有更多的含義,前者爲正向預查,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,後者爲負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。

 


 

反向引用

 

對一個正則表達式模式或部分模式兩邊添加圓括號將致使相關匹配存儲到一個臨時緩衝區中,所捕獲的每一個子匹配都按照在正則表達式模式中從左到右出現的順序存儲。緩衝區編號從 1 開始,最多可存儲 99 個捕獲的子表達式。每一個緩衝區均可以使用 \n 訪問,其中 n 爲一個標識特定緩衝區的一位或兩位十進制數。

 

可使用非捕獲元字符 ?:、?= 或 ?! 來重寫捕獲,忽略對相關匹配的保存。

 

反向引用的最簡單的、最有用的應用之一,是提供查找文本中兩個相同的相鄰單詞的匹配項的能力。如下面的句子爲例:

 

Is is the cost of of gasoline going up up?

 

上面的句子很顯然有多個重複的單詞。若是能設計一種方法定位該句子,而沒必要查找每一個單詞的重複出現,那該有多好。下面的正則表達式使用單個子表達式來實現這一點:

 

實例

查找重複的單詞:

var str = "Is is the cost of of gasoline going up up";
var patt1 = /\b([a-z]+) \1\b/ig;
document.write(str.match(patt1));

 

捕獲的表達式,正如 [a-z]+ 指定的,包括一個或多個字母。正則表達式的第二部分是對之前捕獲的子匹配項的引用,即,單詞的第二個匹配項正好由括號表達式匹配。\1 指定第一個子匹配項。

 

字邊界元字符確保只檢測整個單詞。不然,諸如 "is issued" 或 "this is" 之類的詞組將不能正確地被此表達式識別。

 

正則表達式後面的全局標記 g 指定將該表達式應用到輸入字符串中可以查找到的儘量多的匹配。

 

表達式的結尾處的不區分大小寫 i 標記指定不區分大小寫。

 

多行標記指定換行符的兩邊可能出現潛在的匹配。

 

反向引用還能夠將通用資源指示符 (URI) 分解爲其組件。假定您想將下面的 URI 分解爲協議(ftp、http 等等)、域地址和頁/路徑:

 

https://www.cnblogs.com:80/RM-Anton/p/9427492.html

 

下面的正則表達式提供該功能:

 

實例

輸出全部匹配的數據:

var str = "https://www.cnblogs.com:80/RM-Anton/p/9427492.html"; 
var patt1
= /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
arr = str.match(patt1);
for (var i = 0;i < arr.length ; i++)
{
document.write(arr[i]);
document.write(
"<br>");
}

 

 

第一個括號子表達式捕獲 Web 地址的協議部分。該子表達式匹配在冒號和兩個正斜槓前面的任何單詞。

 

第二個括號子表達式捕獲地址的域地址部分。子表達式匹配 : 和 / 以後的一個或多個字符。

 

第三個括號子表達式捕獲端口號(若是指定了的話)。該子表達式匹配冒號後面的零個或多個數字。只能重複一次該子表達式。

 

最後,第四個括號子表達式捕獲 Web 地址指定的路徑和 / 或頁信息。該子表達式能匹配不包括 # 或空格字符的任何字符序列。

 

將正則表達式應用到上面的 URI,各子匹配項包含下面的內容:

 

      • 第一個括號子表達式包含   https
      • 第二個括號子表達式包含   www.cnblogs.com
      • 第三個括號子表達式包含   :80
      • 第四個括號子表達式包含   /RM-Anton/p/9427492.html

 

元字符

 

 

下表包含了元字符的完整列表以及它們在正則表達式上下文中的行爲:

字符 描述
\

將下一個字符標記爲一個特殊字符、或一個原義字符、或一個 向後引用、或一個八進制轉義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。

^

匹配輸入字符串的開始位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 以後的位置。

$

匹配輸入字符串的結束位置。若是設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 以前的位置。

*

匹配前面的子表達式零次或屢次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。

+

匹配前面的子表達式一次或屢次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。

?

匹配前面的子表達式零次或一次。例如,"do(es)?" 能夠匹配 "do" 或 "does" 。? 等價於 {0,1}。

{n}

n 是一個非負整數。匹配肯定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',可是能匹配 "food" 中的兩個 o。

{n,}

n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的全部 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。

{n,m}

m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。

?

當該字符緊跟在任何一個其餘限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串 "oooo",'o+?' 將匹配單個 "o",而 'o+' 將匹配全部 'o'。

.

匹配除換行符(\n、\r)以外的任何單個字符。要匹配包括 '\n' 在內的任何字符,請使用像"(.|\n)"的模式。

(pattern)

匹配 pattern 並獲取這一匹配。所獲取的匹配能夠從產生的 Matches 集合獲得,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 '\(' 或 '\)'。

(?:pattern)

匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供之後使用。這在使用 "或" 字符 (|) 來組合一個模式的各個部分是頗有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries' 更簡略的表達式。

(?=pattern)

正向確定預查(look ahead positive assert),在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。

(?!pattern)

正向否認預查(negative assert),在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。

(?<=pattern) 反向(look behind)確定預查,與正向確定預查相似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。
(?<!pattern) 反向否認預查,與正向否認預查相似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。
x|y

匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。

[xyz]

字符集合。匹配所包含的任意一個字符。例如, '[abc]' 能夠匹配 "plain" 中的 'a'。

[^xyz]

負值字符集合。匹配未包含的任意字符。例如, '[^abc]' 能夠匹配 "plain" 中的'p'、'l'、'i'、'n'。

[a-z]

字符範圍。匹配指定範圍內的任意字符。例如,'[a-z]' 能夠匹配 'a' 到 'z' 範圍內的任意小寫字母字符。

[^a-z]

負值字符範圍。匹配任何不在指定範圍內的任意字符。例如,'[^a-z]' 能夠匹配任何不在 'a' 到 'z' 範圍內的任意字符。

\b

匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 能夠匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B

匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\cx

匹配由 x 指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。不然,將 c 視爲一個原義的 'c' 字符。

\d

匹配一個數字字符。等價於 [0-9]。

\D

匹配一個非數字字符。等價於 [^0-9]。

\f

匹配一個換頁符。等價於 \x0c 和 \cL。

\n

匹配一個換行符。等價於 \x0a 和 \cJ。

\r

匹配一個回車符。等價於 \x0d 和 \cM。

\s

匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。

\S

匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。

\t

匹配一個製表符。等價於 \x09 和 \cI。

\v

匹配一個垂直製表符。等價於 \x0b 和 \cK。

\w

匹配字母、數字、下劃線。等價於'[A-Za-z0-9_]'。

\W

匹配非字母、數字、下劃線。等價於 '[^A-Za-z0-9_]'。

\xn

匹配 n,其中 n 爲十六進制轉義值。十六進制轉義值必須爲肯定的兩個數字長。例如,'\x41' 匹配 "A"。'\x041' 則等價於 '\x04' & "1"。正則表達式中可使用 ASCII 編碼。

\num

匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,'(.)\1' 匹配兩個連續的相同字符。

\n

標識一個八進制轉義值或一個向後引用。若是 \n 以前至少 n 個獲取的子表達式,則 n 爲向後引用。不然,若是 n 爲八進制數字 (0-7),則 n 爲一個八進制轉義值。

\nm

標識一個八進制轉義值或一個向後引用。若是 \nm 以前至少有 nm 個得到子表達式,則 nm 爲向後引用。若是 \nm 以前至少有 n 個獲取,則 n 爲一個後跟文字 m 的向後引用。若是前面的條件都不知足,若 n 和 m 均爲八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。

\nml

若是 n 爲八進制數字 (0-3),且 m 和 l 均爲八進制數字 (0-7),則匹配八進制轉義值 nml。

\un

匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如, \u00A9 匹配版權符號 (?)。

 

運算符優先級

正則表達式從左到右進行計算,並遵循優先級順序,這與算術表達式很是相似。

相同優先級的從左到右進行運算,不一樣優先級的運算先高後低。下表從最高到最低說明了各類正則表達式運算符的優先級順序:

運算符 描述
\ 轉義符
(), (?:), (?=), [] 圓括號和方括號
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \任何元字符、任何字符 定位點和序列(即:位置和順序)
| 替換,"或"操做
字符具備高於替換運算符的優先級,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",請使用括號建立子表達式,從而產生"(m|f)ood"。

 

匹配規則

 

基本模式匹配

 

一切從最基本的開始。模式,是正則表達式最基本的元素,它們是一組描述字符串特徵的字符。模式能夠很簡單,由普通的字符串組成,也能夠很是複雜,每每用特殊的字符表示一個範圍內的字符、重複出現,或表示上下文。例如:

 

^once

 

這個模式包含一個特殊的字符^,表示該模式只匹配那些以once開頭的字符串。例如該模式與字符串"once upon a time"匹配,與"There once was a man from NewYork"不匹配。正如如^符號表示開頭同樣,$符號用來匹配那些以給定模式結尾的字符串。

 

bucket$

 

這個模式與"Who kept all of this cash in a bucket"匹配,與"buckets"不匹配。字符^和$同時使用時,表示精確匹配(字符串與模式同樣)。例如:

 

^bucket$

 

只匹配字符串"bucket"。若是一個模式不包括^和$,那麼它與任何包含該模式的字符串匹配。例如:模式

 

once

 

與字符串

 

There once was a man from NewYork Who kept all of his cash in a bucket.

 

是匹配的。

 

在該模式中的字母(o-n-c-e)是字面的字符,也就是說,他們表示該字母自己,數字也是同樣的。其餘一些稍微複雜的字符,如標點符號和白字符(空格、製表符等),要用到轉義序列。全部的轉義序列都用反斜槓(\)打頭。製表符的轉義序列是:\t。因此若是咱們要檢測一個字符串是否以製表符開頭,能夠用這個模式:

 

^\t 

 

相似的,用\n表示"新行",\r表示回車。其餘的特殊符號,能夠用在前面加上反斜槓,如反斜槓自己用\\表示,句號.用\.表示,以此類推。

 

字符簇

 

在INTERNET的程序中,正則表達式一般用來驗證用戶的輸入。當用戶提交一個FORM之後,要判斷輸入的電話號碼、地址、EMAIL地址、信用卡號碼等是否有效,用普通的基於字面的字符是不夠的。

 

因此要用一種更自由的描述咱們要的模式的辦法,它就是字符簇。要創建一個表示全部元音字符的字符簇,就把全部的元音字符放在一個方括號裏:

 

[AaEeIiOoUu]

 

這個模式與任何元音字符匹配,但只能表示一個字符。用連字號能夠表示一個字符的範圍,如:

 

[a-z] //匹配全部的小寫字母  [A-Z] //匹配全部的大寫字母  [a-zA-Z] //匹配全部的字母  [0-9] //匹配全部的數字  [0-9\.\-] //匹配全部的數字,句號和減號  [ \f\r\t\n] //匹配全部的白字符

 

一樣的,這些也只表示一個字符,這是一個很是重要的。若是要匹配一個由一個小寫字母和一位數字組成的字符串,好比"z2"、"t6"或"g7",但不是"ab2"、"r2d3" 或"b52"的話,用這個模式:

 

^[a-z][0-9]$

 

儘管[a-z]表明26個字母的範圍,但在這裏它只能與第一個字符是小寫字母的字符串匹配。

 

前面曾經提到^表示字符串的開頭,但它還有另一個含義。當在一組方括號裏使用^是,它表示"非"或"排除"的意思,經常用來剔除某個字符。還用前面的例子,咱們要求第一個字符不能是數字:

 

^[^0-9][0-9]$

 

這個模式與"&5"、"g7"及"-2"是匹配的,但與"12"、"66"是不匹配的。下面是幾個排除特定字符的例子:

 

[^a-z] //除了小寫字母之外的全部字符  [^\\\/\^] //除了(\)(/)(^)以外的全部字符  [^\"\'] //除了雙引號(")和單引號(')以外的全部字符

 

特殊字符"." (點,句號)在正則表達式中用來表示除了"新行"以外的全部字符。因此模式"^.5$"與任何兩個字符的、以數字5結尾和以其餘非"新行"字符開頭的字符串匹配。模式"."能夠匹配任何字符串,除了空串和只包括一個"新行"的字符串。

 

PHP的正則表達式有一些內置的通用字符簇,列表以下:

 

字符簇 描述
[[:alpha:]] 任何字母
[[:digit:]] 任何數字
[[:alnum:]] 任何字母和數字
[[:space:]] 任何空白字符
[[:upper:]] 任何大寫字母
[[:lower:]] 任何小寫字母
[[:punct:]] 任何標點符號
[[:xdigit:]] 任何16進制的數字,至關於[0-9a-fA-F]

 

肯定重複出現

 

到如今爲止,你已經知道如何去匹配一個字母或數字,但更多的狀況下,可能要匹配一個單詞或一組數字。一個單詞有若干個字母組成,一組數字有若干個單數組成。跟在字符或字符簇後面的花括號({})用來肯定前面的內容的重複出現的次數。

 

字符簇 描述
^[a-zA-Z_]$ 全部的字母和下劃線
^[[:alpha:]]{3}$ 全部的3個字母的單詞
^a$ 字母a
^a{4}$ aaaa
^a{2,4}$ aa,aaa或aaaa
^a{1,3}$ a,aa或aaa
^a{2,}$ 包含多於兩個a的字符串
^a{2,} 如:aardvark和aaab,但apple不行
a{2,} 如:baad和aaa,但Nantucket不行
\t{2} 兩個製表符
.{2} 全部的兩個字符

 

這些例子描述了花括號的三種不一樣的用法。一個數字 {x} 的意思是前面的字符或字符簇只出現x次 ;一個數字加逗號 {x,} 的意思是前面的內容出現x或更多的次數 ;兩個數字用逗號分隔的數字 {x,y} 表示 前面的內容至少出現x次,但不超過y次。咱們能夠把模式擴展到更多的單詞或數字:

 

^[a-zA-Z0-9_]{1,}$ // 全部包含一個以上的字母、數字或下劃線的字符串  ^[1-9][0-9]{0,}$ // 全部的正整數  ^\-{0,1}[0-9]{1,}$ // 全部的整數  ^[-]?[0-9]+\.?[0-9]+$ // 全部的浮點數

 

最後一個例子不太好理解,是嗎?這麼看吧:以一個可選的負號 ([-]?) 開頭 (^)、跟着1個或更多的數字([0-9]+)、和一個小數點(\.)再跟上1個或多個數字([0-9]+),而且後面沒有其餘任何東西($)。下面你將知道可以使用的更爲簡單的方法。

 

特殊字符 ? 與 {0,1} 是相等的,它們都表明着: 0個或1個前面的內容 或 前面的內容是可選的 。因此剛纔的例子能夠簡化爲:

 

^\-?[0-9]{1,}\.?[0-9]{1,}$

 

特殊字符 * 與 {0,} 是相等的,它們都表明着 0 個或多個前面的內容 。最後,字符 + 與 {1,} 是相等的,表示 1 個或多個前面的內容 ,因此上面的4個例子能夠寫成:

 

^[a-zA-Z0-9_]+$ // 全部包含一個以上的字母、數字或下劃線的字符串  ^[1-9][0-9]*$ // 全部的正整數  ^\-?[0-9]+$ // 全部的整數  ^\-?[0-9]+\.?[0-9]*$ // 全部的浮點數

 

固然這並不能從技術上下降正則表達式的複雜性,但可使它們更容易閱讀。

 

實例

簡單表達式

正則表達式的最簡單形式是在搜索字符串中匹配其自己的單個普通字符。例如,單字符模式,如 A,不論出如今搜索字符串中的何處,它老是匹配字母 A。下面是一些單字符正則表達式模式的示例:

/a/ /7/ /M/

能夠將許多單字符組合起來以造成大的表達式。例如,如下正則表達式組合了單字符表達式:a、7 和 M。

/a7M/

請注意,沒有串聯運算符。只須在一個字符後面鍵入另外一個字符。

字符匹配

句點 (.) 匹配字符串中的各類打印或非打印字符,只有一個字符例外。這個例外就是換行符 (\n)。下面的正則表達式匹配 aac、abc、acc、adc 等等,以及 a1c、a2c、a-c 和 a#c:

/a.c/

若要匹配包含文件名的字符串,而句點 (.) 是輸入字符串的組成部分,請在正則表達式中的句點前面加反斜槓 (\) 字符。舉例來講明,下面的正則表達式匹配 filename.ext:

/filename\.ext/

這些表達式只讓您匹配"任何"單個字符。可能須要匹配列表中的特定字符組。例如,可能須要查找用數字表示的章節標題(Chapter 一、Chapter 2 等等)。

中括號表達式

若要建立匹配字符組的一個列表,請在方括號([ 和 ])內放置一個或更多單個字符。當字符括在中括號內時,該列表稱爲"中括號表達式"。與在任何別的位置同樣,普通字符在中括號內表示其自己,即,它在輸入文本中匹配一次其自己。大多數特殊字符在中括號表達式內出現時失去它們的意義。不過也有一些例外,如:

  • 若是 ] 字符不是第一項,它結束一個列表。若要匹配列表中的 ] 字符,請將它放在第一位,緊跟在開始 [ 後面。
  • \ 字符繼續做爲轉義符。若要匹配 \ 字符,請使用 \\。

括在中括號表達式中的字符只匹配處於正則表達式中該位置的單個字符。如下正則表達式匹配 Chapter 一、Chapter 二、Chapter 三、Chapter 4 和 Chapter 5:

/Chapter [12345]/

請注意,單詞 Chapter 和後面的空格的位置相對於中括號內的字符是固定的。中括號表達式指定的只是匹配緊跟在單詞 Chapter 和空格後面的單個字符位置的字符集。這是第九個字符位置。

若要使用範圍代替字符自己來表示匹配字符組,請使用連字符 (-) 將範圍中的開始字符和結束字符分開。單個字符的字符值肯定範圍內的相對順序。下面的正則表達式包含範圍表達式,該範圍表達式等效於上面顯示的中括號中的列表。

/Chapter [1-5]/

當以這種方式指定範圍時,開始值和結束值二者都包括在範圍內。注意,還有一點很重要,按 Unicode 排序順序,開始值必須在結束值的前面。

若要在中括號表達式中包括連字符,請採用下列方法之一:

  • 用反斜槓將它轉義:
    [\-]
  • 將連字符放在中括號列表的開始或結尾。下面的表達式匹配全部小寫字母和連字符:
    [-a-z] [a-z-]
  • 建立一個範圍,在該範圍中,開始字符值小於連字符,而結束字符值等於或大於連字符。下面的兩個正則表達式都知足這一要求:
    [!--] [!-~]

若要查找不在列表或範圍內的全部字符,請將插入符號 (^) 放在列表的開頭。若是插入字符出如今列表中的其餘任何位置,則它匹配其自己。下面的正則表達式匹配一、二、三、4 或 5 以外的任何數字和字符:

/Chapter [^12345]/

在上面的示例中,表達式在第九個位置匹配 一、二、三、4 或 5 以外的任何數字和字符。這樣,例如,Chapter 7 就是一個匹配項,Chapter 9 也是一個匹配項。

上面的表達式可使用連字符 (-) 來表示:

/Chapter [^1-5]/

中括號表達式的典型用途是指定任何大寫或小寫字母或任何數字的匹配。下面的表達式指定這樣的匹配:

/[A-Za-z0-9]/

替換和分組

替換使用 | 字符來容許在兩個或多個替換選項之間進行選擇。例如,能夠擴展章節標題正則表達式,以返回比章標題範圍更廣的匹配項。可是,這並不象您可能認爲的那樣簡單。替換匹配 | 字符任一側最大的表達式。

您可能認爲,下面的表達式匹配出如今行首和行尾、後面跟一個或兩個數字的 Chapter 或 Section:

/^Chapter|Section [1-9][0-9]{0,1}$/

很遺憾,上面的正則表達式要麼匹配行首的單詞 Chapter,要麼匹配行尾的單詞 Section 及跟在其後的任何數字。若是輸入字符串是 Chapter 22,那麼上面的表達式只匹配單詞 Chapter。若是輸入字符串是 Section 22,那麼該表達式匹配 Section 22。

若要使正則表達式更易於控制,可使用括號來限制替換的範圍,即,確保它只應用於兩個單詞 Chapter 和 Section。可是,括號也用於建立子表達式,並可能捕獲它們以供之後使用,這一點在有關反向引用的那一節講述。經過在上面的正則表達式的適當位置添加括號,就可使該正則表達式匹配 Chapter 1 或 Section 3。

下面的正則表達式使用括號來組合 Chapter 和 Section,以便表達式正確地起做用:

/^(Chapter|Section) [1-9][0-9]{0,1}$/

儘管這些表達式正常工做,但 Chapter|Section 周圍的括號還將捕獲兩個匹配字中的任一個供之後使用。因爲在上面的表達式中只有一組括號,所以,只有一個被捕獲的"子匹配項"。

在上面的示例中,您只須要使用括號來組合單詞 Chapter 和 Section 之間的選擇。若要防止匹配被保存以備未來使用,請在括號內正則表達式模式以前放置 ?:。下面的修改提供相同的能力而不保存子匹配項:

/^(?:Chapter|Section) [1-9][0-9]{0,1}$/

除 ?: 元字符外,兩個其餘非捕獲元字符建立被稱爲"預測先行"匹配的某些內容。正向預測先行使用 ?= 指定,它匹配處於括號中匹配正則表達式模式的起始點的搜索字符串。反向預測先行使用 ?! 指定,它匹配處於與正則表達式模式不匹配的字符串的起始點的搜索字符串。

例如,假設您有一個文檔,該文檔包含指向 Windows 3.一、Windows 9五、Windows 98 和 Windows NT 的引用。再進一步假設,您須要更新該文檔,將指向 Windows 9五、Windows 98 和 Windows NT 的全部引用更改成 Windows 2000。下面的正則表達式(這是一個正向預測先行的示例)匹配 Windows 9五、Windows 98 和 Windows NT:

/Windows(?=95 |98 |NT )/

找到一處匹配後,緊接着就在匹配的文本(不包括預測先行中的字符)以後搜索下一處匹配。例如,若是上面的表達式匹配 Windows 98,將在 Windows 以後而不是在 98 以後繼續搜索。

其餘示例

下面列出一些正則表達式示例:

正則表達式 描述
/\b([a-z]+) \1\b/gi 一個單詞連續出現的位置。
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 將一個URL解析爲協議、域、端口及相對路徑。
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章節的位置。
/[-a-z]/ a至z共26個字母再加一個-號。
/ter\b/ 可匹配chapter,而不能匹配terminal。
/\Bapt/ 可匹配chapter,而不能匹配aptitude。
/Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,當找到一個匹配後,從Windows後面開始進行下一次的檢索匹配。
/^\s*$/ 匹配空行。
/\d{2}-\d{5}/ 驗證由兩位數字、一個連字符再加 5 位數字組成的 ID 號。
/<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/ 匹配 HTML 標記。
相關文章
相關標籤/搜索