正則表達(dá)式
1.常用的元字符
代碼
說明
.
匹配除換行符以外的任意字符
\w
匹配字母或數(shù)字或下劃線或漢字
\s
匹配任意的空白符
\d
匹配數(shù)字
\b
匹配單詞的開始或結(jié)束
^
匹配字符串的開始
$
匹配字符串的結(jié)束
+匹配重復(fù)1次或更多次
*匹配重復(fù)任意次(可能是0次)
有些正則表達(dá)式處理工具還有一個(gè)處理多行的選項(xiàng)集索。如果選中了這個(gè)選項(xiàng)澳淑,^和$的意義就變成了匹配行的開始處和結(jié)束處。
轉(zhuǎn)義字符:
如果要查找.或者*轻掩,必須使用轉(zhuǎn)義字符鳞尔,\.和\*,這樣才能查找出.和*
例如:deerchao\.net匹配deerchao.net
C:\\Windows匹配C:\Windows
2.常用的限定符
代碼/語法
說明
*
重復(fù)零次或更多次
+
重復(fù)一次或更多次
?
重復(fù)零次或一次
{n}
重復(fù)n次
{n,}
重復(fù)n次或更多次
{n,m}
重復(fù)n到m次
例如:
Windows\d+匹配Windows后面跟1個(gè)或更多數(shù)字
^\w+匹配一行的第一個(gè)單詞(或整個(gè)字符串的第一個(gè)單詞,具體匹配哪個(gè)意思得看選項(xiàng)設(shè)置)
3.字符類
[aeiou]匹配任何一個(gè)英文元音字母
[.?!]匹配標(biāo)點(diǎn)符號
[0-9]0到9任意一位數(shù)字智玻,與\d含義一致
[a-z0-9A-Z]等同于\w
?能出現(xiàn)0次或1次
4.分枝條件
正則表達(dá)式里的分枝條件指的是有幾種規(guī)則,如果滿足其中任意一種規(guī)則都應(yīng)該當(dāng)成匹配芙代,具體方法是用|把不同的規(guī)則分隔開尚困。
注意:使用分枝條件時(shí),要注意各個(gè)條件的順序链蕊。原因是匹配分枝條件時(shí)事甜,將會從左到右的測試每個(gè)條件,如果滿足了某個(gè)分枝的話滔韵,就不會再去管其他的條件了逻谦。
5.反義
常用的反義代碼
代碼/語法
說明
\W
匹配任意不是字母,數(shù)字陪蜻,下劃線邦马,漢字的字符
\S
匹配任意不是空白符的字符
\D
匹配任意非數(shù)字的字符
\B
匹配不是單詞開頭或結(jié)束的位置
[^x]
匹配除了x以外的任意字符
[^aeiou]
匹配除了aeiou這幾個(gè)字母以外的任意字符
例子:\S+匹配不包含空白符的字符串
]+>匹配用尖括號括起來的以a開頭的字符串
6.后向引用
后向應(yīng)用用于重復(fù)搜索前面某個(gè)分組匹配的文本。
6.1規(guī)則:從左向右宴卖,以分組的左括號為標(biāo)志滋将,第一個(gè)出現(xiàn)的分組的組號為1,第二個(gè)為2症昏,以此類推随闽。
6.2常用分組語法
分類
代碼/語法
說明
捕獲
(exp)
匹配exp,并捕獲文本到自動命名的組里
(?exp)
匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?'name'exp)
(?:exp)
匹配exp,不捕獲匹配的文本肝谭,也不給此分組分配組號
零寬斷言
(?=exp)
匹配exp前面的位置
(?<=exp)
匹配exp后面的位置
(?!exp)
匹配后面跟的不是exp的位置
(?
匹配前面不是exp的位置
注釋
(?#comment)
這種類型的分組不對正則表達(dá)式的處理產(chǎn)生任何影響掘宪,用于提供注釋讓人閱讀
第三個(gè)(?:exp)不會改變正則表達(dá)式的處理方式,只是這樣的組匹配的內(nèi)容不會像前兩種那樣被捕獲到某個(gè)組里面攘烛,也不會擁有組號魏滚。
7.領(lǐng)寬斷言
7.1(?=exp)也叫零寬度正預(yù)測先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp坟漱。比如\b\w+(?=ing\b)鼠次,匹配以ing結(jié)尾的單詞的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.時(shí)芋齿,它會匹配sing和danc腥寇。
7.2(?<=exp)也叫零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp沟突。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的后半部分(除了re以外的部分)花颗,例如在查找reading a book時(shí),它匹配ading惠拭。
例子:下面這個(gè)例子同時(shí)使用了這兩種斷言:(?<=\s)\d+(?=\s)匹配以空白符間隔的數(shù)字(再次強(qiáng)調(diào)扩劝,不包括這些空白符)庸论。
8.負(fù)向零寬斷言
8.1零寬度負(fù)預(yù)測先行斷言(?!exp),斷言此位置的后面不能匹配表達(dá)式exp棒呛。例如:\d{3}(?!\d)匹配三位數(shù)字聂示,而且這三位數(shù)字的后面不能是數(shù)字;\b((?!abc)\w)+\b匹配不包含連續(xù)字符串a(chǎn)bc的單詞簇秒。
8.2同理鱼喉,我們可以用(?零寬度負(fù)回顧后發(fā)斷言來斷言此位置的前面不能匹配表達(dá)式exp:(?
8.3請?jiān)敿?xì)分析表達(dá)式(?<=<(\w+)>).*(?=<\/\1>),這個(gè)表達(dá)式最能表現(xiàn)零寬斷言的真正用途趋观。
一個(gè)更復(fù)雜的例子:(?<=<(\w+)>).*(?=<\/\1>)匹配不包含屬性的簡單HTML標(biāo)簽內(nèi)里的內(nèi)容扛禽。(?<=<(\w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是),然后是.*(任意的字符串),最后是一個(gè)后綴(?=<\/\1>)皱坛。注意后綴里的\/编曼,它用到了前面提過的字符轉(zhuǎn)義;\1則是一個(gè)反向引用剩辟,引用的正是捕獲的第一組掐场,前面的(\w+)匹配的內(nèi)容,這樣如果前綴實(shí)際上是的話贩猎,后綴就是了熊户。整個(gè)表達(dá)式匹配的是和之間的內(nèi)容(再次提醒,不包括前綴和后綴本身)吭服。
注意:請?jiān)敿?xì)分析表達(dá)式(?<=<(\w+)>).*(?=<\/\1>)嚷堡,這個(gè)表達(dá)式最能表現(xiàn)零寬斷言的真正用途。
9.注釋
9.1小括號的另一種用途是通過語法(?#comment)來包含注釋噪馏。
9.2要包含注釋的話麦到,最好是啟用“忽略模式里的空白符”選項(xiàng)绿饵,這樣在編寫表達(dá)式時(shí)能任意的添加空格欠肾,Tab,換行拟赊,而實(shí)際使用時(shí)這些都將被忽略刺桃。啟用這個(gè)選項(xiàng)后,在#后面到這一行結(jié)束的所有文本都將被當(dāng)成注釋忽略掉吸祟。
9.3例如:
(?<=#斷言要匹配的文本的前綴
<(\w+)> #查找尖括號括起來的字母或數(shù)字(即HTML/XML標(biāo)簽)
)#前綴結(jié)束
.*#匹配任意文本
(?=#斷言要匹配的文本的后綴
<\/\1>#查找尖括號括起來的內(nèi)容:前面是一個(gè)"/"瑟慈,后面是先前捕獲的標(biāo)簽
)#后綴結(jié)束
10.貪婪與懶惰
當(dāng)正則表達(dá)式中包含能接受重復(fù)的限定符時(shí),通常的行為是(在使整個(gè)表達(dá)式能得到匹配的前提下)匹配盡可能多的字符屋匕。以這個(gè)表達(dá)式為例:a.*b葛碧,它將會匹配最長的以a開始,以b結(jié)束的字符串过吻。如果用它來搜索aabab的話进泼,它會匹配整個(gè)字符串a(chǎn)abab蔗衡。這被稱為貪婪匹配。
有時(shí)乳绕,我們更需要懶惰匹配绞惦,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式洋措,只要在它后面加上一個(gè)問號?济蝉。這樣.*?就意味著匹配任意數(shù)量的重復(fù),但是在能使整個(gè)匹配成功的前提下使用最少的重復(fù)〔しⅲ現(xiàn)在看看懶惰版的例子吧:
a.*?b匹配最短的王滤,以a開始,以b結(jié)束的字符串滓鸠。如果把它應(yīng)用于aabab的話淑仆,它會匹配aab(第一到第三個(gè)字符)和ab(第四到第五個(gè)字符)。
10.1懶惰限定符
代碼/語法
說明
*?
重復(fù)任意次哥力,但盡可能少重復(fù)
+?
重復(fù)1次或更多次蔗怠,但盡可能少重復(fù)
??
重復(fù)0次或1次,但盡可能少重復(fù)
{n,m}?
重復(fù)n到m次吩跋,但盡可能少重復(fù)
{n,}?
重復(fù)n次以上寞射,但盡可能少重復(fù)
11.處理選項(xiàng)
11.1常用的處理選項(xiàng)
名稱
說明
IgnoreCase(忽略大小寫)
匹配時(shí)不區(qū)分大小寫。
Multiline(多行模式)
更改^和$的含義锌钮,使它們分別在任意一行的行首和行尾匹配桥温,而不僅僅在整個(gè)字符串的開頭和結(jié)尾匹配。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結(jié)束前的位置.)
Singleline(單行模式)
更改.的含義梁丘,使它與每一個(gè)字符匹配(包括換行符\n)侵浸。
IgnorePatternWhitespace(忽略空白)
忽略表達(dá)式中的非轉(zhuǎn)義空白并啟用由#標(biāo)記的注釋。
ExplicitCapture(顯式捕獲)
僅捕獲已被顯式命名的組氛谜。
注:一個(gè)經(jīng)常被問到的問題是:是不是只能同時(shí)使用多行模式和單行模式中的一種掏觉?答案是:不是。這兩個(gè)選項(xiàng)之間沒有任何關(guān)系值漫,除了它們的名字比較相似(以至于讓人感到疑惑)以外澳腹。
12.平衡組/遞歸匹配
這里介紹的平衡組語法是由.Net Framework支持的;其它語言/庫不一定支持這種功能杨何,或者支持此功能但需要使用不同的語法酱塔。
12.1這里需要用到以下的語法構(gòu)造:
?(?'group')把捕獲的內(nèi)容命名為group,并壓入堆棧(Stack)
?(?'-group')從堆棧上彈出最后壓入堆棧的名為group的捕獲內(nèi)容,如果堆棧本來為空危虱,則本分組的匹配失敗
?(?(group)yes|no)如果堆棧上存在以名為group的捕獲內(nèi)容的話羊娃,繼續(xù)匹配yes部分的表達(dá)式,否則繼續(xù)匹配no部分
(?!)零寬負(fù)向先行斷言埃跷,由于沒有后綴表達(dá)式蕊玷,試圖匹配總是失敗
我們需要做的是每碰到了左括號芦瘾,就在壓入一個(gè)"Open",每碰到一個(gè)右括號,就彈出一個(gè)集畅,到了最后就看看堆棧是否為空--如果不為空那就證明左括號比右括號多近弟,那匹配就應(yīng)該失敗。正則表達(dá)式引擎會進(jìn)行回溯(放棄最前面或最后面的一些字符)挺智,盡量使整個(gè)表達(dá)式得到匹配祷愉。
<#最外層的左括號
[^<>]*#最外層的左括號后面的不是括號的內(nèi)容
(
(
(?'Open'<)#碰到了左括號,在黑板上寫一個(gè)"Open"
[^<>]*#匹配左括號后面的不是括號的內(nèi)容
)+
(
(?'-Open'>)#碰到了右括號赦颇,擦掉一個(gè)"Open"
[^<>]*#匹配右括號后面不是括號的內(nèi)容
)+
)*
(?(Open)(?!))#在遇到最外層的右括號前面二鳄,判斷黑板上還有沒有沒擦掉的"Open";如果還有媒怯,則匹配失敗
>#最外層的右括號
平衡組的一個(gè)最常見的應(yīng)用就是匹配HTML,下面這個(gè)例子可以匹配嵌套的
標(biāo)簽:]*>[^<>]*(((?'Open']*>)[^<>]*)+((?'-Open'
)[^<>]*)+)*(?(Open)(?!)).
13.補(bǔ)充
13.1尚未詳細(xì)討論的語法
代碼/語法
說明
\a
報(bào)警字符(打印它的效果是電腦嘀一聲)
\b
通常是單詞分界位置订讼,但如果在字符類里使用代表退格
\t
制表符,Tab
\r
回車
\v
豎向制表符
\f
換頁符
\n
換行符
\e
Escape
\0nn
ASCII代碼中八進(jìn)制代碼為nn的字符
\xnn
ASCII代碼中十六進(jìn)制代碼為nn的字符
\unnnn
Unicode代碼中十六進(jìn)制代碼為nnnn的字符
\cN
ASCII控制字符扇苞。比如\cC代表Ctrl+C
\A
字符串開頭(類似^欺殿,但不受處理多行選項(xiàng)的影響)
\Z
字符串結(jié)尾或行尾(不受處理多行選項(xiàng)的影響)
\z
字符串結(jié)尾(類似$,但不受處理多行選項(xiàng)的影響)
\G
當(dāng)前搜索的開頭
\p{name}
Unicode中命名為name的字符類鳖敷,例如\p{IsGreek}
(?>exp)
貪婪子表達(dá)式
(?-exp)
平衡組
(?im-nsx:exp)
在子表達(dá)式exp中改變處理選項(xiàng)
(?im-nsx)
為表達(dá)式后面的部分改變處理選項(xiàng)
(?(exp)yes|no)
把exp當(dāng)作零寬正向先行斷言脖苏,如果在這個(gè)位置能匹配,使用yes作為此組的表達(dá)式定踱;否則使用no
(?(exp)yes)
同上棍潘,只是使用空表達(dá)式作為no
(?(name)yes|no)
如果命名為name的組捕獲到了內(nèi)容,使用yes作為表達(dá)式崖媚;否則使用no
(?(name)yes)
同上亦歉,只是使用空表達(dá)式作為no