元字符
\ba\w\b匹配以字母a開頭的單詞——先是某個單詞開始處(\b)示辈,然后是字母a,然后是任意數(shù)量的字母或數(shù)字(\w),最后是單詞結束處(\b)沧竟。
\d+匹配1個或更多連續(xù)的數(shù)字前翎。這里的+是和類似的元字符杆融,不同的是匹配重復任意次(可能是0次)燃乍,而+則匹配重復1次或更多次唆樊。
\b\w{6}\b 匹配剛好6個字符的單詞。
元字符(和數(shù)字6在同一個鍵位上的符號)和$都匹配一個位置刻蟹,這和\b有點類似逗旁。^匹配你要用來查找的字符串的開頭,$匹配結尾舆瘪。這兩個代碼在驗證輸入的內容時非常有用片效,比如一個網(wǎng)站如果要求你填寫的QQ號必須為5位到12位數(shù)字時,可以使用:\d{5,12}$英古。
字符轉義
如果你想查找元字符本身的話淀衣,比如你查找.,或者,就出現(xiàn)了問題:你沒辦法指定它們,因為它們會被解釋成別的意思召调。這時你就得使用\來取消這些字符的特殊意義膨桥。因此,你應該使用.和唠叛。當然只嚣,要查找\本身,你也得用.
重復
下面是正則表達式中所有的限定符(指定數(shù)量的代碼玻墅,例如*,{5,12}等):
下面是一些使用重復的例子:
Windows\d+匹配Windows后面跟1個或更多數(shù)字
^\w+匹配一行的第一個單詞(或整個字符串的第一個單詞介牙,具體匹配哪個意思得看選項設置)
分組
上面提到了怎么重復單個字符(直接在字符后面加上限定符就行了);但如果想要重復多個字符又該怎么辦澳厢?你可以用小括號來指定子表達式(也叫做分組)环础,然后你就可以指定這個子表達式的重復次數(shù)了,你也可以對子表達式進行其它一些操作(后面會有介紹)剩拢。
(\d{1,3}.){3}\d{1,3}是一個簡單的IP地址匹配表達式线得。要理解這個表達式,請按下列順序分析它:\d{1,3}匹配1到3位的數(shù)字徐伐,(\d{1,3}.){3}匹配三位數(shù)字加上一個英文句號(這個整體也就是這個分組)重復3次贯钩,最后再加上一個一到三位的數(shù)字(\d{1,3})。
不幸的是办素,它也將匹配256.300.888.999這種不可能存在的IP地址角雷。如果能使用算術比較的話,或許能簡單地解決這個問題性穿,但是正則表達式中并不提供關于數(shù)學的任何功能勺三,所以只能使用冗長的分組,選擇需曾,字符類來描述一個正確的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?祈远,這里我就不細說了,你自己應該能分析得出來它的意義商源。
反義
有時需要查找不屬于某個能簡單定義的字符類的字符车份。比如想查找除了數(shù)字以外,其它任意字符都行的情況牡彻,這時需要用到反義:
例子:\S+匹配不包含空白符的字符串扫沼。
<a>+>匹配用尖括號括起來的以a開頭的字符串。
后向引用
后向引用用于重復搜索前面某個分組匹配的文本讨便。例如充甚,\1代表分組1匹配的文本。難以理解霸褒?請看示例:
\b(\w+)\b\s+\1\b可以用來匹配重復的單詞,像go go, 或者kitty kitty盈蛮。這個表達式首先是一個單詞废菱,也就是單詞開始處和結束處之間的多于一個的字母或數(shù)字(\b(\w+)\b),這個單詞會被捕獲到編號為1的分組中抖誉,然后是1個或幾個空白符(\s+)殊轴,最后是分組1中捕獲的內容(也就是前面匹配的那個單詞)(\1)。
也可以自己指定子表達式的組名袒炉。要指定一個子表達式的組名旁理,請使用這樣的語法:(?<Word>\w+)(或者把尖括號換成'也行:(?'Word'\w+)),這樣就把\w+的組名指定為Word了。要反向引用這個分組捕獲的內容我磁,你可以使用\k<Word>,所以上一個例子也可以寫成這樣:\b(?<Word>\w+)\b\s+\k<Word>\b孽文。
使用小括號的時候,還有很多特定用途的語法夺艰。下面列出了最常用的一些:
零寬斷言
接下來的四個用于查找在某些內容(但并不包括這些內容)之前或之后的東西芋哭,也就是說它們像\b,^,$那樣用于指定一個位置,這個位置應該滿足一定的條件(即斷言)郁副,因此它們也被稱為零寬斷言减牺。最好還是拿例子來說明吧:
(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達式exp存谎。比如\b\w+(?=ing\b)拔疚,匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.時既荚,它會匹配sing和danc稚失。
(?<=exp)也叫零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達式exp固以。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的后半部分(除了re以外的部分)墩虹,例如在查找reading a book時嘱巾,它匹配ading。
假如你想要給一個很長的數(shù)字中每三位間加一個逗號(當然是從右邊加起了)诫钓,你可以這樣查找需要在前面和里面添加逗號的部分:((?<=\d)\d{3})+\b旬昭,用它對1234567890進行查找時結果是234567890。
下面這個例子同時使用了這兩種斷言:(?<=\s)\d+(?=\s)匹配以空白符間隔的數(shù)字(再次強調菌湃,不包括這些空白符)问拘。
負向零寬斷言
前面我們提到過怎么查找不是某個字符或不在某個字符類里的字符的方法(反義)。但是如果我們只是想要確保某個字符沒有出現(xiàn)惧所,但并不想去匹配它時怎么辦骤坐?例如,如果我們想查找這樣的單詞--它里面出現(xiàn)了字母q,但是q后面跟的不是字母u,我們可以嘗試這樣:
\b\wqu\w\b匹配包含后面不是字母u的字母q的單詞下愈。但是如果多做測試(或者你思維足夠敏銳纽绍,直接就觀察出來了),你會發(fā)現(xiàn)势似,如果q出現(xiàn)在單詞的結尾的話拌夏,像Iraq,Benq,這個表達式就會出錯履因。這是因為u總要匹配一個字符障簿,所以如果q是單詞的最后一個字符的話,后面的u將會匹配q后面的單詞分隔符(可能是空格栅迄,或者是句號或其它的什么)站故,后面的\w\b將會匹配下一個單詞,于是\b\wqu\w\b就能匹配整個Iraq fighting毅舆。負向零寬斷言能解決這樣的問題西篓,因為它只匹配一個位置,并不消費任何字符±时現(xiàn)在污淋,我們可以這樣來解決這個問題:\b\wq(?!u)\w*\b。
零寬度負預測先行斷言(?!exp)余掖,斷言此位置的后面不能匹配表達式exp寸爆。例如:\d{3}(?!\d)匹配三位數(shù)字,而且這三位數(shù)字的后面不能是數(shù)字盐欺;\b((?!abc)\w)+\b匹配不包含連續(xù)字符串a(chǎn)bc的單詞赁豆。
同理,我們可以用(?<!exp),零寬度負回顧后發(fā)斷言來斷言此位置的前面不能匹配表達式exp:(?<![a-z])\d{7}匹配前面不是小寫字母的七位數(shù)字冗美。
一個更復雜的例子:(?<=<(\w+)>).(?=</\1>)匹配不包含屬性的簡單HTML標簽內里的內容魔种。(?<=<(\w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是<b>),然后是.(任意的字符串),最后是一個后綴(?=</\1>)粉洼。注意后綴里的/节预,它用到了前面提過的字符轉義叶摄;\1則是一個反向引用,引用的正是捕獲的第一組安拟,前面的(\w+)匹配的內容蛤吓,這樣如果前綴實際上是的話,后綴就是了糠赦。整個表達式匹配的是和之間的內容(再次提醒会傲,不包括前綴和后綴本身)。
貪婪與懶惰
當正則表達式中包含能接受重復的限定符時拙泽,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符淌山。以這個表達式為例:a.b,它將會匹配最長的以a開始顾瞻,以b結束的字符串泼疑。如果用它來搜索aabab的話,它會匹配整個字符串a(chǎn)abab朋其。這被稱為貪婪匹配王浴。
有時,我們更需要懶惰匹配梅猿,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式秒裕,只要在它后面加上一個問號?袱蚓。這樣.?就意味著匹配任意數(shù)量的重復,但是在能使整個匹配成功的前提下使用最少的重復〖蛤撸現(xiàn)在看看懶惰版的例子吧:
a.*?b匹配最短的喇潘,以a開始,以b結束的字符串梭稚。如果把它應用于aabab的話颖低,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。