正則表達式學習

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}QQ512使225,12512 的意義就變成了匹配行的開始處和結束處。
  • 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,就留下nono也基本上不做其他操作,只是返回個表示匹配成功或失敗的標誌.這裏用(?!)來表示匹配失敗.前面有講過零寬斷言.它就是一種特殊的斷言.所以我們大部分時候的是這樣用(?(group)(?!)     //判斷棧裏面的元素爲空。
在這裏舉個比較簡單的例子.要假如有一字符串.要匹配其中以第一個左尖括號後面開始出現的尖括號對<>裏的內容:
string source = "**<a<b<arwen>c>other>**";
string pattern ="[^<>]*  #匹配任何非尖括號的字符
                    (?'group'<)    #匹配<並且入棧
                    [^<>]*        #匹配任意非尖括號的字符
                    (?'-group'>)   #匹配>並且出棧
                    [^<>]*         #匹配任意非尖括號的字符
                    (?(group)(?!))   #判斷棧中是否爲空,爲空則匹配成功,否則失敗
                    ";
結果是 : b<arwen>c
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章