PHP正規表示式完全手冊

傑克.陳發表於2015-06-24
原文:PHP正規表示式完全手冊
php的正規表示式完全手冊

前言

   正規表示式是煩瑣的,但是強大的,學會之後的應用會讓你除了提高效率外,會給你帶來絕對的成就感。只要認真去閱讀這些資料,加上應用的時候進行一定的參考,掌握正規表示式不是問題。

索引

   1._引子
   2._正規表示式的歷史
   3._正規表示式定義

    3.1_普通字元
    3.2_非列印字元
    3.3_特殊字元
    3.4_限定符
    3.5_定位符
    3.6_選擇
    3.7_後向引用

   4._各種操作符的運算優先順序
   5._全部符號解釋
   6._部分例子
   7._正規表示式匹配規則

    7.1_基本模式匹配
    7.2_字元簇
    7.3_確定重複出現
1. 引子
   目前,正規表示式已經在很多軟體中得到廣泛的應用,包括*nix(Linux, Unix等),HP等作業系統,PHP,C#,Java等開發環境,以及很多的應用軟體中,都可以看到正規表示式的影子。

   正規表示式的使用,可以通過簡單的辦法來實現強大的功能。為了簡單有效而又不失強大,造成了正規表示式程式碼的難度較大,學習起來也不是很容易,所以需要付出一些努力才行,入門之後參照一定的參考,使用起來還是比較簡單有效的。

   例子: ^.+@.+\..+$

   這樣的程式碼曾經多次把我自己給嚇退過。可能很多人也是被這樣的程式碼給嚇跑的吧。繼續閱讀本文將讓你也可以自由應用這樣的程式碼。

   注意:這裡的第7部分跟前面的內容看起來似乎有些重複,目的是把前面表格裡的部分重新描述了一次,目的是讓這些內容更容易理解。
2. 正規表示式的歷史

   正規表示式的“祖先”可以一直上溯至對人類神經系統如何工作的早期研究。Warren McCulloch 和 Walter Pitts 這兩位神經生理學家研究出一種數學方式來描述這些神經網路。

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

   隨後,發現可以將這一工作應用於使用 Ken Thompson 的計算搜尋演算法的一些早期研究,Ken Thompson 是 Unix 的主要發明人。正規表示式的第一個實用應用程式就是 Unix 中的 qed 編輯器。

   如他們所說,剩下的就是眾所周知的歷史了。從那時起直至現在正規表示式都是基於文字的編輯器和搜尋工具中的一個重要部分。

3. 正規表示式定義

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

   列目錄時, dir *.txt或ls *.txt中的*.txt就不是一個正規表示式,因為這裡*與正則式的*的含義是不同的。

   正規表示式是由普通字元(例如字元 a 到 z)以及特殊字元(稱為元字元)組成的文字模式。正規表示式作為一個模板,將某個字元模式與所搜尋的字串進行匹配。

   3.1 普通字元

   由所有那些未顯式指定為元字元的列印和非列印字元組成。這包括所有的大寫和小寫字母字元,所有數字,所有標點符號以及一些符號。

   3.2 非列印字元

字元 含義
cx 匹配由x指明的控制字元。例如, cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 `c` 字元。
f 匹配一個換頁符。等價於 x0c 和 cL。

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

 匹配一個回車符。等價於 x0d 和 cM。
s 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於 [ f

	v]。
S 匹配任何非空白字元。等價於 [^ f

	v]。
	 匹配一個製表符。等價於 x09 和 cI。
v 匹配一個垂直製表符。等價於 x0b 和 cK。

 
   3.3 特殊字元

   所謂特殊字元,就是一些有特殊含義的字元,如上面說的"*.txt"中的*,簡單的說就是表示任何字串的意思。如果要查詢檔名中有*的檔案,則需要對*進行轉義,即在其前加一個。ls *.txt。正規表示式有以下特殊字元。

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

 

   構造正規表示式的方法和建立數學表示式的方法一樣。也就是用多種元字元與操作符將小的表示式結合在一起來建立更大的表示式。正規表示式的元件可以是單個的字元、字符集合、字元範圍、字元間的選擇或者所有這些元件的任意組合。
 

   3.4 限定符

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

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

   正規表示式的限定符有:

字元 描述
* 匹配前面的子表示式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表示式一次或多次。例如,`zo+` 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
? 匹配前面的子表示式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"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?`。請注意在逗號和兩個數之間不能有空格。

   3.5 定位符

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

   3.6 選擇

   用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被快取,此時可用?:放在第一個選項前來消除這種副作用。

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

   3.7 後向引用

  對一個正規表示式模式或部分模式兩邊新增圓括號將導致相關匹配儲存到一個臨時緩衝區中,所捕獲的每個子匹配都按照在正規表示式模式中從左至右所遇到的內容儲存。儲存子匹配的緩衝區編號從 1 開始,連續編號直至最大 99 個子表示式。每個緩衝區都可以使用 `
` 訪問,其中 n 為一個標識特定緩衝區的一位或兩位十進位制數。

   可以使用非捕獲元字元 `?:`, `?=`, or `?!` 來忽略對相關匹配的儲存。

4. 各種操作符的運算優先順序

   相同優先順序的從左到右進行運算,不同優先順序的運算先高後低。各種操作符的優先順序從高到低如下:

操作符 描述
 轉義符
(), (?:), (?=), [] 圓括號和方括號
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, anymetacharacter 位置和順序
| “或”操作

5. 全部符號解釋

字元 描述
 將下一個字元標記為一個特殊字元、或一個原義字元、或一個 向後引用、或一個八進位制轉義符。例如,`n` 匹配字元 "n"。`
` 匹配一個換行符。序列 `\` 匹配 "" 而 ""則匹配"("。匹配輸入字串的開始位置。如果設定了RegExp物件的Multiline屬性,也匹配′
′或′
′之後的位置。$匹配輸入字串的結束位置。如果設定了RegExp物件的Multiline屬性,$也匹配′
′或′
′之前的位置。∗匹配前面的子表示式零次或多次。例如,zo∗能匹配"z"以及"zoo"。∗等價於0,。+匹配前面的子表示式一次或多次。例如,′zo+′能匹配"zo"以及"zoo",但不能匹配"z"。+等價於1,。?匹配前面的子表示式零次或一次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等價於0,1。nn是一個非負整數。匹配確定的n次。例如,′o2′不能匹配"Bob"中的′o′,但是能匹配"food"中的兩個o。n,n是一個非負整數。至少匹配n次。例如,′o2,′不能匹配"Bob"中的′o′,但能匹配"foooood"中的所有o。′o1,′等價於′o+′。′o0,′則等價於′o∗′。n,mm和n均為非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,"o1,3"將匹配"fooooood"中的前三個o。′o0,1′等價於′o?′。請注意在逗號和兩個數之間不能有空格。?當該字元緊跟在任何一個其他限制符(∗,+,?,n,n,,n,m)後面時,匹配模式是非貪婪的。非貪婪模式儘可能少的匹配所搜尋的字串,而預設的貪婪模式則儘可能多的匹配所搜尋的字串。例如,對於字串"oooo",′o+?′將匹配單個"o",而′o+′將匹配所有′o′。.匹配除"
"之外的任何單個字元。要匹配包括′
′在內的任何字元,請使用象′[.
]′的模式。(pattern)匹配pattern並獲取這一匹配。所獲取的匹配可以從產生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字元,請使用′(′或′`。
(?:pattern) 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行儲存供以後使用。這在使用 "或" 字元 (|) 來組合一個模式的各個部分是很有用。例如, `industr(?:y|ies) 就是一個比 `industry|industries` 更簡略的表示式。
(?=pattern) 正向預查,在任何匹配 pattern 的字串開始處匹配查詢字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如,`Windows (?=95|98|NT|2000)` 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始。
(?!pattern) 負向預查,在任何不匹配 pattern 的字串開始處匹配查詢字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如`Windows (?!95|98|NT|2000)` 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始
x|y 匹配 x 或 y。例如,`z|food` 能匹配 "z" 或 "food"。`(z|f)ood` 則匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一個字元。例如, `[abc]` 可以匹配 "plain" 中的 `a`。
[^xyz] 負值字符集合。匹配未包含的任意字元。例如, `[^abc]` 可以匹配 "plain" 中的`p`。
[a-z] 字元範圍。匹配指定範圍內的任意字元。例如,`[a-z]` 可以匹配 `a` 到 `z` 範圍內的任意小寫字母字元。
[^a-z] 負值字元範圍。匹配任何不在指定範圍內的任意字元。例如,`[^a-z]` 可以匹配任何不在 `a` 到 `z` 範圍內的任意字元。
 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, `er` 可以匹配"never" 中的 `er`,但不能匹配 "verb" 中的 `er`。
B 匹配非單詞邊界。`erB` 能匹配 "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。

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

 匹配一個回車符。等價於 x0d 和 cM。
s 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於 [ f

	v]。
S 匹配任何非空白字元。等價於 [^ f

	v]。
	 匹配一個製表符。等價於 x09 和 cI。
v 匹配一個垂直製表符。等價於 x0b 和 cK。
w 匹配包括下劃線的任何單詞字元。等價於`[A-Za-z0-9_]`。
W 匹配任何非單詞字元。等價於 `[^A-Za-z0-9_]`。
xn 匹配 n,其中 n 為十六進位制轉義值。十六進位制轉義值必須為確定的兩個數字長。例如,`x41` 匹配 "A"。`x041` 則等價於 `x04` & "1"。正規表示式中可以使用 ASCII 編碼。.

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

 標識一個八進位制轉義值或一個向後引用。如果 
 之前至少 n 個獲取的子表示式,則 n 為向後引用。否則,如果 n 為八進位制數字 (0-7),則 n 為一個八進位制轉義值。

m 標識一個八進位制轉義值或一個向後引用。如果 
m 之前至少有 nm 個獲得子表示式,則 nm 為向後引用。如果 
m 之前至少有 n 個獲取,則 n 為一個後跟文字 m 的向後引用。如果前面的條件都不滿足,若 n 和 m 均為八進位制數字 (0-7),則 
m 將匹配八進位制轉義值 nm。

ml 如果 n 為八進位制數字 (0-3),且 m 和 l 均為八進位制數字 (0-7),則匹配八進位制轉義值 nml。
un 匹配 n,其中 n 是一個用四個十六進位制數字表示的 Unicode 字元。例如, u00A9 匹配版權符號 (?)。
 
6. 部分例子

正規表示式 說明
/([a-z]+) 1/gi 一個單詞連續出現的位置
/(w+)://([^/:]+)(:d*)?([^# ]*)/ 將一個URL解析為協議、域、埠及相對路徑
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章節的位置
/[-a-z]/ A至z共26個字母再加一個-號。
/ter/ 可匹配chapter,而不能terminal
/Bapt/ 可匹配chapter,而不能aptitude
/Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,當找到一個匹配後,從Windows後面開始進行下一次

7. 正規表示式匹配規則

   7.1 基本模式匹配

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

   ^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)是字面的字元,也就是說,他們表示該字母本身,數字也是一樣的。其他一些稍微複雜的字元,如標點符號和白字元(空 格、製表符等),要用到轉義序列。所有的轉義序列都用反斜槓()打頭。製表符的轉義序列是:	。所以如果我們要檢測一個字串是否以製表符開頭,可以 用這個模式:

   ^	

   類似的,用
表示“新行”,
表示回車。其他的特殊符號,可以用在前面加上反斜槓,如反斜槓本身用\表示,句號.用.表示,以此類推。

   7.2 字元簇

   在INTERNET的程式中,正規表示式通常用來驗證使用者的輸入。當使用者提交一個FORM以後,要判斷輸入的電話號碼、地址、EMAIL地址、信用卡號碼等是否有效,用普通的基於字面的字元是不夠的。

   所以要用一種更自由的描述我們要的模式的辦法,它就是字元簇。要建立一個表示所有母音字元的字元簇,就把所有的母音字元放在一個方括號裡:

   [AaEeIiOoUu]

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

   [a-z] //匹配所有的小寫字母
   [A-Z] //匹配所有的大寫字母
   [a-zA-Z] //匹配所有的字母
   [0-9] //匹配所有的數字
   [0-9.-] //匹配所有的數字,句號和減號
   [ f
	
] //匹配所有的白字元

   同樣的,這些也只表示一個字元,這是一個非常重要的。如果要匹配一個由一個小寫字母和一位數字組成的字串,比如"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]

   7.3 確定重複出現

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

   字元簇 含義
   ^[a-zA-Z_]所有的字母和下劃線  [[:alpha:]]3 所有的3個字母的單詞
   ^a字母a  a4 aaaa
   ^a{2,4}aa,aaa或aaaa  a1,3 a,aa或aaa
   ^a{2,}$ 包含多於兩個a的字串
   ^a{2,} 如:aardvark和aaab,但apple不行
   a{2,} 如:baad和aaa,但Nantucket不行
   	{2} 兩個製表符
   .{2} 所有的兩個字元

  這些例子描述了花括號的三種不同的用法。一個數字,{x}的意思是“前面的字元或字元簇只出現x次”;一個數字加逗號,{x,}的意思是“前面的內容出現 x或更多的次數”;兩個用逗號分隔的數字,{x,y}表示“前面的內容至少出現x次,但不超過y次”。我們可以把模式擴充套件到更多的單詞或數字:

   ^[a-zA-Z0-9_]{1,}//所有包含一個以上的字母、數字或下劃線的字串  [0−9]1, //所有的正數
   ^-{0,1}[0-9]{1,}//所有的整數  -0,1[0−9]0,.0,1[0−9]0, //所有的小數

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

   特殊字元"?"與{0,1}是相等的,它們都代表著:“0個或1個前面的內容”或“前面的內容是可選的”。所以剛才的例子可以簡化為:

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

   特殊字元"*"與{0,}是相等的,它們都代表著“0個或多個前面的內容”。最後,字元"+"與 {1,}是相等的,表示“1個或多個前面的內容”,所以上面的4個例子可以寫成:

   ^[a-zA-Z0-9_]+//所有包含一個以上的字母、數字或下劃線的字串  [0−9]+ //所有的正數
   ^-?[0-9]+//所有的整數  -?[0−9]∗.?[0−9]∗ //所有的小數

   當然這並不能從技術上降低正規表示式的複雜性,但可以使它們更容易閱讀。


詳細出處參考:http://www.jb51.net/article/26215.htm

 


相關文章