1 轉載-感謝
[1 30分鐘入門]
(http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html#mission)[2 平衡組講的清楚]
(http://blog.csdn.net/weiwenhp/article/details/7664504)[3 常用的正則表達式]
(http://blog.csdn.net/onebigday/article/details/5429868)
一 簡單匹配實例
- 1 hi
精確匹配這樣的字符串:由兩個字符組成,前一個字符是h,後一個是i - 2 \bhi\b
精確地查找hi這個單詞 - 3 \bhi\b.*\bLucy\bLucy\b
先是一個單詞hi,然後是任意個任意字符(但不能是換行),最後是Lucy這個單詞。 - 4 0\d\d-\d\d\d\d\d\d\d\d
匹配這樣的字符串:以0開頭,然後是兩個數字,然後是一個連字號“-”,最後是8個數字(也就是中國的電話號碼。當然,這個例子只能匹配區號爲3位的情形)。 - 5 0\d{2}-\d{8}:避免上面麻煩
這裏\d後面的{2}({8})的意思是前面\d必須連續重複匹配2次(8次)。 - 6 \ba\w*\b
匹配以字母a開頭的單詞——先是某個單詞開始處(\b),然後是字母a,然後是任意數量的字母或數字(\w*),最後是單詞結束處(\b)。 - 7 \b\w{6}\b
匹配剛好6個字符的單詞。 - 8 \^\d{5,12}
一個網站如果要求你填寫的QQ號必須爲5位到12位數字時,可以使用。2匹配只能不多不少重復2次,5,12則是重復的次數不能少於5次,不能多於12次。和忽略大小寫的選項類似,有些正則表達式處理工具還有一個處理多行的選項。如果選中了這個選項,和 的意義就變成了匹配行的開始處和結束處。 - 9 字符轉義:unibetter.com 匹配unibetter.com 。 C:\Windows匹配C:\Windows。
- 10 Windows\d+
匹配Windows後面跟1個或更多數字 - 11 \^\w+
匹配一行的第一個單詞(或整個字符串的第一個單詞,具體匹配哪個意思得看選項設置) - 12 [aeiou]
就匹配任何一個英文元音字母,
[.?!]
匹配標點符號(.或?或!)。 - 13 指定一個字符範圍:
[0-9]
代表的含意與\d就是完全一致的:一位數字;
[a-z0-9A-Z_]
也完全等同於\w(如果只考慮英文的話)。 - 14 (?0\d{2}[) -]?\d{8}
匹配幾種格式的電話號碼,像(010)88886666,或022-22334455,或02912345678 ;
也匹配010)12345678或(022-87654321這樣的“不正確”的格式。
分析:首先是一個轉義字符(,它能出現0次或1次(?),然後是一個0,後面跟着2個數字(\d{2}),然後是)或-或空格中的一個,它出現1次或不出現(?),最後是8個數字(\d{8})。 - 15 0\d{2}-\d{8}|0\d{3}-\d{7}
這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)。 - 16 (0\d{2})[- ]?\d{8}|0\d{2}[- ]?\d{8} |(0\d{3})[- ]?\d{7}|0\d{3}[- ]?\d{7}
匹配3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔。 - 17 使用分枝條件時,要注意各個條件的順序。匹配分枝條件時,將會從左到右地測試每個條件,如果滿足了某個分枝的話,就不會去再管其它的條件了。
\d{5}-\d{4}|\d{5}這個表達式用於匹配美國的郵政編碼。美國郵編的規則是5位數字,或者用連字號間隔的9位數字。
\d{5}|\d{5}-\d{4}的話,那麼就只會匹配5位的郵編(以及9位郵編的前5位)。 - 18 (\d{1,3}.){3}\d{1,3}
是一個簡單的IP地址匹配表達式。
分析:\d{1,3}匹配1到3位的數字,(\d{1,3}.){3}匹配三位數字加上一個英文句號(這個整體也就是這個分組)重複3次,最後再加上一個一到三位的數字(\d{1,3})。
也可能匹配 256.300.888.999
-19 ((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
描述一個正確的IP地址,用到了: 分組() 選擇 ? 字符類[] 轉義\ 重複{n}
-20
二 元字符
- \b 代表着單詞的開頭或結尾,也就是單詞的分界處。如果需要更精確的說法,\b匹配這樣的位置:它的前一個字符和後一個字符不全是(一個是,一個不是或不存在)\w。
- . 匹配除了換行符以外的任意字符.
- 前邊的內容可以連續重複使用任意次以使整個表達式得到匹配.
- .* 連在一起就意味着任意數量的不包含換行的字符.
- 換行符就是’\n’,ASCII編碼爲10(十六進制0x0A)的字符。
- \d 匹配一位數字(0,或1,或2,或……)
- 不是元字符,只匹配它本身——連字符(或者減號,或者中橫線,或者隨你怎麼稱呼它)。
- \s 匹配任意的空白符,包括空格,製表符(Tab),換行符,中文全角空格等
- \w 匹配字母或數字或下劃線或漢字等。
- 對中文/漢字的特殊處理是由.Net提供的正則表達式引擎支持的,其它環境下的具體情況請查看相關文檔。
- \d+ 匹配1個或更多連續的數字。
這裏的+是和類似的元字符,不同的是匹配重複任意次(可能是0次),而+則匹配重複1次或更多次。 - ^ (和數字6在同一個鍵位上的符號)和
都匹配一個位置,這和\b有點類似。匹配你要用來查找的字符串的開頭, 匹配結尾。 - $ 匹配結尾。
- (
- )
- ? 選擇
三 字符轉義。
- \ 如果你想查找元字符本身的話,比如你查找.,或者*,使用\來取消這些字符的特殊意義。因此,你應該使用.和*。當然,要查找\本身,你也得用\.
重複
- 重複零次或更多次
- 重複一次或更多次
- ? 重複零次或一次
- {n} 重複n次
- {n,} 重複n次或更多次
- {n,m} 重複n到m次
四 字符類
- 想匹配沒有預定義元字符的字符集合(比如元音字母a,e,i,o,u),需要在方括號裏列出它們就行。
- [ ] 也可以指定範圍
五 分支條件
- 正則表達式裏的分枝條件指的是有幾種規則,如果滿足其中任意一種規則都應該當成匹配,具體方法是用|把不同的規則分隔開。
六 分組
- 用小括號來指定子表達式(也叫做分組),然後你就可以指定這個子表達式的重複次數了。
- 也可以對子表達式進行其它一些操作(後面會有介紹)。
七 反義 :想查找除了數字以外,其它任意字符都行的情況,這時需要用到反義。
- \W 匹配任意不是字母,數字,下劃線,漢字的字符
- \S 匹配任意不是空白符的字符
- \D 匹配任意非數字的字符
- \B 匹配不是單詞開頭或結束的位置
- [\^x] 匹配除了x以外的任意字符
- [\^aeiou] 匹配除了aeiou這幾個字母以外的任意字符
20 \S+ 匹配不包含空白符的字符串。
21 <a[^>]+> 匹配用尖括號括起來的以a開頭的字符串。
八 後向引用(建議從這開始看原文,不好精簡了)
- 後向引用用於重複搜索前面某個分組匹配的文本.
- 匹配這個子表達式的文本(也就是此分組捕獲的內容)可以在表達式或其它程序中作進一步的處理。
默認情況下,每個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。 - \1代表分組1匹配的文本
- 指定子表達式的組名
(?\w+)(或者把尖括號換成’也行:(?’Word’\w+)),這樣就把\w+的組名指定爲Word了。
要反向引用這個分組捕獲的內容,你可以使用\k.
表4.常用分組語法
分類 代碼/語法 說明
捕獲 (exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<name>exp) 匹配exp,並捕獲文本到名稱爲name的組裏,也可以寫成(?'name'exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
----------------------------------------------
零寬斷言 (?=exp) 匹配exp前面的位置 reading --> read
(?<=exp) 匹配exp後面的位置 reading --> ading
(?!exp) 匹配後面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
---------------------------------------------------
註釋 (?#comment) 這種類型的分組不對正則表達式的處理產生任何影響,用於提供註釋讓人閱讀
- \b(\w+)\b\s+\1\b
可以用來匹配重複的單詞,像go go, 或者kitty kitty。
分析: 這個表達式首先是一個單詞,也就是單詞開始處和結束處之間的多於一個的字母或數字(\b(\w+)\b),這個單詞會被捕獲到編號爲1的分組中,然後是1個或幾個空白符(\s+),最後是分組1中捕獲的內容(也就是前面匹配的那個單詞)(\1)。
- \b(?<Word>\w+)\b\s+\k<Word>\b。
上一個例子也可以寫成這樣。
九 零寬斷言:查找在 exp 之前或者之後(不包括這麼內容)的東西
- (?=exp) :零寬度正預測先行斷言 : 斷言自身出現的位置的後面能匹配表達式exp。
- \b\w+(?=ing\b)
匹配以ing結尾的單詞的前面部分(除了ing以外的部分),
如查找I'm singing while you're dancing.時,它會匹配sing和danc。
- (?<=exp) 零寬度正回顧後發斷言。斷言自身出現的位置的前面能匹配表達式exp。
***
- (?<=\bre)\w+\b
會匹配以re開頭的單詞的後半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。
- ((?<=\d)\d{3})+\b
想要給一個很長的數字中每三位間加一個逗號(當然是從右邊加起了).
十 負向零寬斷言
- 它只匹配一個位置,並不消費任何字符。現在,我們可以這樣來解決這個問題:\b\w*q(?!u)\w*\b。
- (?!u):零寬度負預測先行斷言(?!exp),斷言此位置的後面不能匹配表達式exp
- \b\w*q[^u]\w*\b
匹配包含後面不是字母u的字母q的單詞
也匹配:Iraq fighting 錯誤格式。
- \b\w*q(?!u)\w*\b
- \d{3}(?!\d)
匹配三位數字,而且這三位數字的後面不能是數字
- \b((?!abc)\w)+\b
匹配不包含連續字符串abc的單詞。
- (?<=<(\w+)>).*(?=<\/\1>) :最能表現零寬斷言的真正用途。 注意 不是V,是\ /
匹配不包含屬性的簡單HTML標籤內裏的內容。
(?<=<(\w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是<b>),
然後是.*(任意的字符串),最後是一個後綴(?=<\/\1>)。注意後綴裏的\/,
它用到了前面提過的字符轉義;\1則是一個反向引用,引用的正是捕獲的第一組,
前面的(\w+)匹配的內容,這樣如果前綴實際上是<b>的話,後綴就是</b>了。
整個表達式匹配的是<b>和</b>之間的內容(再次提醒,不包括前綴和後綴本身)。
十一 註釋 : 小括號的另一種用途是通過語法(?#comment)來包含註釋
- 要包含註釋的話,最好是啓用“忽略模式裏的空白符”選項.
- 2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。
- 可以前面的一個表達式寫成這樣:
(?<= # 斷言要匹配的文本的前綴
<(\w+)> # 查找尖括號括起來的字母或數字(即HTML/XML標籤)
) # 前綴結束
.* # 匹配任意文本
(?= # 斷言要匹配的文本的後綴
<\/\1> # 查找尖括號括起來的內容:前面是一個"/",後面是先前捕獲的標籤
) # 後綴結束
十二 貪婪與懶惰
- 當正則表達式中包含能接受重複的限定符時,通常的行爲是(在使整個表達式能得到匹配的前提下)匹配儘可能多的字符.
- 爲什麼第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)?
簡單地說,因爲正則表達式有另一條規則,比懶惰/貪婪規則的優先級更高:最先開始的匹配擁有最高的優先權——The match that begins earliest wins。 - .*?就意味着匹配任意數量的重複,但是在能使整個匹配成功的前提下使用最少的重複。
表5.懶惰限定符
代碼/語法 說明
*? 重複任意次,但儘可能少重複
+? 重複1次或更多次,但儘可能少重複
?? 重複0次或1次,但儘可能少重複
{n,m}? 重複n到m次,但儘可能少重複
{n,}? 重複n次以上,但儘可能少重複
- a.*b,它將會匹配最長的以a開始,以b結束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串aabab。這被稱爲貪婪匹配。
- a.*?b匹配最短的,以a開始,以b結束的字符串。如果把它應用於aabab的話,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。
十三 處理選項
表6.常用的處理選項
名稱 說明
IgnoreCase(忽略大小寫) 匹配時不區分大小寫。
Multiline(多行模式) 更改^和$的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結尾匹配。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結束前的位置.)
Singleline(單行模式) 更改.的含義,使它與每一個字符匹配(包括換行符\n)。
IgnorePatternWhitespace(忽略空白) 忽略表達式中的非轉義空白並啓用由#標記的註釋。
ExplicitCapture(顯式捕獲) 僅捕獲已被顯式命名的組。
- 一個經常被問到的問題是:是不是隻能同時使用多行模式和單行模式中的一種?答案是:不是。這兩個選項之間沒有任何關係,除了它們的名字比較相似(以至於讓人感到疑惑)以外。
十四 平衡組 / 遞歸匹配
正則表達式裏是這樣用到棧的
(?'group'exp) 它除了起命名的作用外,後臺的操作就是把exp入棧,假如exp是左括號即(?'group'\().
(?'-group'exp) 這裏多了個-表示出棧.
(?(group)yes|no) 如果堆棧上存在以名爲group的捕獲內容的話,繼續匹配yes部分的表達式,否則繼續匹配no部分.其實這裏yes和no可以去年一個
往往是去掉yes,就留下no而no也基本上不做其他操作,只是返回個表示匹配成功或失敗的標誌.這裏用(?!)來表示匹配失敗.前面有講過零寬斷言.它就是一種特殊的斷言.所以我們大部分時候的是這樣用(?(group)(?!) //判斷棧裏面的元素爲空。
在這裏舉個比較簡單的例子.要假如有一字符串.要匹配其中以第一個左尖括號後面開始出現的尖括號對<>裏的內容:
string source = "**<a<b<arwen>c>other>**";
string pattern ="[^<>]* #匹配任何非尖括號的字符
(?'group'<) #匹配<並且入棧
[^<>]* #匹配任意非尖括號的字符
(?'-group'>) #匹配>並且出棧
[^<>]* #匹配任意非尖括號的字符
(?(group)(?!)) #判斷棧中是否爲空,爲空則匹配成功,否則失敗
";
結果是 : b<arwen>c