正則表達式
1.常用的元字符
代碼
說明
.
匹配除換行符以外的任意字符
\w
匹配字母或數字或下劃線或漢字
\s
匹配任意的空白符
\d
匹配數字
\b
匹配單詞的開始或結束
^
匹配字符串的開始
$
匹配字符串的結束
+匹配重復1次或更多次
*匹配重復任意次(可能是0次)
有些正則表達式處理工具還有一個處理多行的選項。如果選中了這個選項,^和$的意義就變成了匹配行的開始處和結束處。
轉義字符:
如果要查找.或者*,必須使用轉義字符,\.和\*,這樣才能查找出.和*
例如:deerchao\.net匹配deerchao.net
C:\\Windows匹配C:\Windows
2.常用的限定符
代碼/語法
說明
*
重復零次或更多次
+
重復一次或更多次
?
重復零次或一次
{n}
重復n次
{n,}
重復n次或更多次
{n,m}
重復n到m次
例如:
Windows\d+匹配Windows后面跟1個或更多數字
^\w+匹配一行的第一個單詞(或整個字符串的第一個單詞,具體匹配哪個意思得看選項設置)
3.字符類
[aeiou]匹配任何一個英文元音字母
[.?!]匹配標點符號
[0-9]0到9任意一位數字,與\d含義一致
[a-z0-9A-Z]等同于\w
?能出現0次或1次
4.分枝條件
正則表達式里的分枝條件指的是有幾種規則,如果滿足其中任意一種規則都應該當成匹配,具體方法是用|把不同的規則分隔開。
注意:使用分枝條件時,要注意各個條件的順序。原因是匹配分枝條件時,將會從左到右的測試每個條件,如果滿足了某個分枝的話,就不會再去管其他的條件了。
5.反義
常用的反義代碼
代碼/語法
說明
\W
匹配任意不是字母,數字,下劃線,漢字的字符
\S
匹配任意不是空白符的字符
\D
匹配任意非數字的字符
\B
匹配不是單詞開頭或結束的位置
[^x]
匹配除了x以外的任意字符
[^aeiou]
匹配除了aeiou這幾個字母以外的任意字符
例子:\S+匹配不包含空白符的字符串
]+>匹配用尖括號括起來的以a開頭的字符串
6.后向引用
后向應用用于重復搜索前面某個分組匹配的文本。
6.1規則:從左向右,以分組的左括號為標志,第一個出現的分組的組號為1,第二個為2,以此類推。
6.2常用分組語法
分類
代碼/語法
說明
捕獲
(exp)
匹配exp,并捕獲文本到自動命名的組里
(?exp)
匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?'name'exp)
(?:exp)
匹配exp,不捕獲匹配的文本,也不給此分組分配組號
零寬斷言
(?=exp)
匹配exp前面的位置
(?<=exp)
匹配exp后面的位置
(?!exp)
匹配后面跟的不是exp的位置
(?
匹配前面不是exp的位置
注釋
(?#comment)
這種類型的分組不對正則表達式的處理產生任何影響,用于提供注釋讓人閱讀
第三個(?:exp)不會改變正則表達式的處理方式,只是這樣的組匹配的內容不會像前兩種那樣被捕獲到某個組里面,也不會擁有組號。
7.領寬斷言
7.1(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的后面能匹配表達式exp。比如\b\w+(?=ing\b),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.時,它會匹配sing和danc。
7.2(?<=exp)也叫零寬度正回顧后發斷言,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的后半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。
例子:下面這個例子同時使用了這兩種斷言:(?<=\s)\d+(?=\s)匹配以空白符間隔的數字(再次強調,不包括這些空白符)。
8.負向零寬斷言
8.1零寬度負預測先行斷言(?!exp),斷言此位置的后面不能匹配表達式exp。例如:\d{3}(?!\d)匹配三位數字,而且這三位數字的后面不能是數字;\b((?!abc)\w)+\b匹配不包含連續字符串abc的單詞。
8.2同理,我們可以用(?零寬度負回顧后發斷言來斷言此位置的前面不能匹配表達式exp:(?
8.3請詳細分析表達式(?<=<(\w+)>).*(?=<\/\1>),這個表達式最能表現零寬斷言的真正用途。
一個更復雜的例子:(?<=<(\w+)>).*(?=<\/\1>)匹配不包含屬性的簡單HTML標簽內里的內容。(?<=<(\w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是),然后是.*(任意的字符串),最后是一個后綴(?=<\/\1>)。注意后綴里的\/,它用到了前面提過的字符轉義;\1則是一個反向引用,引用的正是捕獲的第一組,前面的(\w+)匹配的內容,這樣如果前綴實際上是的話,后綴就是了。整個表達式匹配的是和之間的內容(再次提醒,不包括前綴和后綴本身)。
注意:請詳細分析表達式(?<=<(\w+)>).*(?=<\/\1>),這個表達式最能表現零寬斷言的真正用途。
9.注釋
9.1小括號的另一種用途是通過語法(?#comment)來包含注釋。
9.2要包含注釋的話,最好是啟用“忽略模式里的空白符”選項,這樣在編寫表達式時能任意的添加空格,Tab,換行,而實際使用時這些都將被忽略。啟用這個選項后,在#后面到這一行結束的所有文本都將被當成注釋忽略掉。
9.3例如:
(?<=#斷言要匹配的文本的前綴
<(\w+)> #查找尖括號括起來的字母或數字(即HTML/XML標簽)
)#前綴結束
.*#匹配任意文本
(?=#斷言要匹配的文本的后綴
<\/\1>#查找尖括號括起來的內容:前面是一個"/",后面是先前捕獲的標簽
)#后綴結束
10.貪婪與懶惰
當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符。以這個表達式為例:a.*b,它將會匹配最長的以a開始,以b結束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串aabab。這被稱為貪婪匹配。
有時,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式,只要在它后面加上一個問號?。這樣.*?就意味著匹配任意數量的重復,但是在能使整個匹配成功的前提下使用最少的重復。現在看看懶惰版的例子吧:
a.*?b匹配最短的,以a開始,以b結束的字符串。如果把它應用于aabab的話,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。
10.1懶惰限定符
代碼/語法
說明
*?
重復任意次,但盡可能少重復
+?
重復1次或更多次,但盡可能少重復
??
重復0次或1次,但盡可能少重復
{n,m}?
重復n到m次,但盡可能少重復
{n,}?
重復n次以上,但盡可能少重復
11.處理選項
11.1常用的處理選項
名稱
說明
IgnoreCase(忽略大小寫)
匹配時不區分大小寫。
Multiline(多行模式)
更改^和$的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結尾匹配。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結束前的位置.)
Singleline(單行模式)
更改.的含義,使它與每一個字符匹配(包括換行符\n)。
IgnorePatternWhitespace(忽略空白)
忽略表達式中的非轉義空白并啟用由#標記的注釋。
ExplicitCapture(顯式捕獲)
僅捕獲已被顯式命名的組。
注:一個經常被問到的問題是:是不是只能同時使用多行模式和單行模式中的一種?答案是:不是。這兩個選項之間沒有任何關系,除了它們的名字比較相似(以至于讓人感到疑惑)以外。
12.平衡組/遞歸匹配
這里介紹的平衡組語法是由.Net Framework支持的;其它語言/庫不一定支持這種功能,或者支持此功能但需要使用不同的語法。
12.1這里需要用到以下的語法構造:
?(?'group')把捕獲的內容命名為group,并壓入堆棧(Stack)
?(?'-group')從堆棧上彈出最后壓入堆棧的名為group的捕獲內容,如果堆棧本來為空,則本分組的匹配失敗
?(?(group)yes|no)如果堆棧上存在以名為group的捕獲內容的話,繼續匹配yes部分的表達式,否則繼續匹配no部分
(?!)零寬負向先行斷言,由于沒有后綴表達式,試圖匹配總是失敗
我們需要做的是每碰到了左括號,就在壓入一個"Open",每碰到一個右括號,就彈出一個,到了最后就看看堆棧是否為空--如果不為空那就證明左括號比右括號多,那匹配就應該失敗。正則表達式引擎會進行回溯(放棄最前面或最后面的一些字符),盡量使整個表達式得到匹配。
<#最外層的左括號
[^<>]*#最外層的左括號后面的不是括號的內容
(
(
(?'Open'<)#碰到了左括號,在黑板上寫一個"Open"
[^<>]*#匹配左括號后面的不是括號的內容
)+
(
(?'-Open'>)#碰到了右括號,擦掉一個"Open"
[^<>]*#匹配右括號后面不是括號的內容
)+
)*
(?(Open)(?!))#在遇到最外層的右括號前面,判斷黑板上還有沒有沒擦掉的"Open";如果還有,則匹配失敗
>#最外層的右括號
平衡組的一個最常見的應用就是匹配HTML,下面這個例子可以匹配嵌套的
標簽:]*>[^<>]*(((?'Open']*>)[^<>]*)+((?'-Open'
)[^<>]*)+)*(?(Open)(?!)).
13.補充
13.1尚未詳細討論的語法
代碼/語法
說明
\a
報警字符(打印它的效果是電腦嘀一聲)
\b
通常是單詞分界位置,但如果在字符類里使用代表退格
\t
制表符,Tab
\r
回車
\v
豎向制表符
\f
換頁符
\n
換行符
\e
Escape
\0nn
ASCII代碼中八進制代碼為nn的字符
\xnn
ASCII代碼中十六進制代碼為nn的字符
\unnnn
Unicode代碼中十六進制代碼為nnnn的字符
\cN
ASCII控制字符。比如\cC代表Ctrl+C
\A
字符串開頭(類似^,但不受處理多行選項的影響)
\Z
字符串結尾或行尾(不受處理多行選項的影響)
\z
字符串結尾(類似$,但不受處理多行選項的影響)
\G
當前搜索的開頭
\p{name}
Unicode中命名為name的字符類,例如\p{IsGreek}
(?>exp)
貪婪子表達式
(?-exp)
平衡組
(?im-nsx:exp)
在子表達式exp中改變處理選項
(?im-nsx)
為表達式后面的部分改變處理選項
(?(exp)yes|no)
把exp當作零寬正向先行斷言,如果在這個位置能匹配,使用yes作為此組的表達式;否則使用no
(?(exp)yes)
同上,只是使用空表達式作為no
(?(name)yes|no)
如果命名為name的組捕獲到了內容,使用yes作為表達式;否則使用no
(?(name)yes)
同上,只是使用空表達式作為no