正則表達式學習筆記
首先推薦一篇入門文章:http://deerchao.net/tutorials/regex/regex.htm#mission
感謝作者
下面先對本文章做一下筆記:
1、 正則表達式是什么:處理字符串的有效工具。
2、 從例子開始學習正則:
表1.常用的元字符
|
代碼
|
說明
|
.
|
匹配除換行符以外的任意字符
|
"w
|
匹配字母或數字或下劃線或漢字
|
"s
|
匹配任意的空白符
|
"d
|
匹配數字
|
"b
|
匹配單詞的開始或結束
|
^
|
匹配字符串的開始
|
$
|
匹配字符串的結束
|
和忽略大小寫的選項類似,有些正則表達式處理工具還有一個處理多行的選項。如果選中了這個選項,^和$的意義就變成了匹配行的開始處和結束處。
3、字符轉義:如果查找元字符本身用"+元字符,如:".表示匹配 . 。
4、重復的處理
表2.常用的限定符
|
代碼/語法
|
說明
|
*
|
重復零次或更多次
|
+
|
重復一次或更多次
|
?
|
重復零次或一次
|
{n}
|
重復n次
|
{n,}
|
重復n次或更多次
|
{n,m}
|
重復n到m次
|
5、字符類
要想查找數字,字母或數字,空白是很簡單的,因為已經有了對應這些字符集合的元字符,但是如果你想匹配沒有預定義元字符的字符集合(比如元音字母a,e,i,o,u),應該怎么辦?
很簡單,你只需要在方括號里列出它們就行了,像[aeiou]就匹配任何一個英文元音字母,[.?!]匹配標點符號(.或?或!)。
6、分支條件
使用分枝條件時,要注意各個條件的順序。如果你把它改成"d{5}|"d{5}-"d{4}的話,那么就只會匹配5位的郵編(以及9位郵編的前5位)。原因是匹配分枝條件時,將會從左到右地測試每個條件,如果滿足了某個分枝的話,就不會去再管其它的條件了。
7、分組
描述一個正確的IP地址:((2[0-4]"d|25[0-5]|[01]?"d"d?)".){3}(2[0-4]"d|25[0-5]|[01]?"d"d?)。
這里面(2[0-4]"d|25[0-5]|[01]?"d"d?)的意義
8、反義
表3.常用的反義代碼
|
代碼/語法
|
說明
|
"W
|
匹配任意不是字母,數字,下劃線,漢字的字符
|
"S
|
匹配任意不是空白符的字符
|
"D
|
匹配任意非數字的字符
|
"B
|
匹配不是單詞開頭或結束的位置
|
[^x]
|
匹配除了x以外的任意字符
|
[^aeiou]
|
匹配除了aeiou這幾個字母以外的任意字符
|
<a[^>]+>匹配用尖括號括起來的以a開頭的字符串。
9、向后引用
后向引用用于重復搜索前面某個分組匹配的文本。例如,"1代表分組1匹配的文本。難以理解?請看示例:
"b("w+)"b"s+"1"b可以用來匹配重復的單詞,像go go, 或者kitty kitty。這個表達式首先是一個單詞,也就是單詞開始處和結束處之間的多于一個的字母或數字("b("w+)"b),這個單詞會被捕獲到編號為1的分組中,然后是1個或幾個空白符("s+),最后是分組1中捕獲的內容(也就是前面匹配的那個單詞)("1)。
表4.常用分組語法
|
分類
|
代碼/語法
|
說明
|
捕獲
|
(exp)
|
匹配exp,并捕獲文本到自動命名的組里
|
(?<name>exp)
|
匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?'name'exp)
|
(?:exp)
|
匹配exp,不捕獲匹配的文本,也不給此分組分配組號
|
零寬斷言
|
(?=exp)
|
匹配exp前面的位置
|
(?<=exp)
|
匹配exp后面的位置
|
(?!exp)
|
匹配后面跟的不是exp的位置
|
(?<!exp)
|
匹配前面不是exp的位置
|
注釋
|
(?#comment)
|
這種類型的分組不對正則表達式的處理產生任何影響,用于提供注釋讓人閱讀
|
(?=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,用它對1234567890進行查找時結果是234567890。
因為對于斷言是指只有當條件為真時才會繼續。上訴正則表達式為了找到匹配字符串,重左至右一次開始只有當到達1時 ,后續字符串滿足條件。
設想 如果從 12345678901 字符串中 獲取 滿足此正則表達式的 應該為 字符串2345678901 。
"b"w*q[^u]"w*"b匹配包含后面不是字母u的字母q的單詞。但是如果多做測試(或者你思維足夠敏銳,直接就觀察出來了),你會發現,如果q出現在單詞的結尾的話,像Iraq,Benq,這個表達式就會出錯。這是因為[^u]總要匹配一個字符,所以如果q是單詞的最后一個字符的話,后面的[^u]將會匹配q后面的單詞分隔符(可能是空格,或者是句號或其它的什么),后面的"w*"b將會匹配下一個單詞,于是"b"w*q[^u]"w*"b就能匹配整個Iraq fighting。負向零寬斷言能解決這樣的問題,因為它只匹配一個位置,并不消費任何字符。現在,我們可以這樣來解決這個問題:"b"w*q(?!u)"w*"b。
零寬度負預測先行斷言(?!exp),斷言此位置的后面不能匹配表達式exp。例如:"d{3}(?!"d)匹配三位數字,而且這三位數字的后面不能是數字;"b((?!abc)"w)+"b匹配不包含連續字符串abc的單詞。
一個更復雜的例子:(?<=<("w+)>).*(?=<"/"1>)匹配不包含屬性的簡單HTML標簽內里的內容。(<?("w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是<b>),然后是.*(任意的字符串),最后是一個后綴(?=<"/"1>)。注意后綴里的"/,它用到了前面提過的字符轉義;"1則是一個反向引用,引用的正是捕獲的第一組,前面的("w+)匹配的內容,這樣如果前綴實際上是<b>的話,后綴就是</b>了。整個表達式匹配的是<b>和</b>之間的內容(再次提醒,不包括前綴和后綴本身)。
10、 注釋
小括號的另一種用途是通過語法(?#comment)來包含注釋。例如:2[0-4]"d(?#200-249)|25[0-5](?#250-255)|[01]?"d"d?(?#0-199)。
(?<= # 斷言要匹配的文本的前綴
<("w+)> # 查找尖括號括起來的字母或數字(即HTML/XML標簽)
) # 前綴結束
.* # 匹配任意文本
(?= # 斷言要匹配的文本的后綴
<"/"1> # 查找尖括號括起來的內容:前面是一個"/",后面是先前捕獲的標簽
) # 后綴結束
表5.懶惰限定符
|
代碼/語法
|
說明
|
*?
|
重復任意次,但盡可能少重復
|
+?
|
重復1次或更多次,但盡可能少重復
|
??
|
重復0次或1次,但盡可能少重復
|
{n,m}?
|
重復n到m次,但盡可能少重復
|
{n,}?
|
重復n次以上,但盡可能少重復
|
11、