全面分析Linux正則表達(dá)式(三)
Linux正則表達(dá)式的模式修正符與元字符在前面兩篇我們已經(jīng)介紹了,因?yàn)榫W(wǎng)上現(xiàn)有的正則表達(dá)式資料都對這部分都有詳細(xì)的介紹和眾多的例子,如果覺得對前一部分缺乏了解可以參看這些資料。本文希望可以盡可能多涉及一些較高級(jí)的正則表達(dá)式特性。
在本文里,我們主要介紹Linux正則表達(dá)式的子模式(subpatterns),逆向引用(Back references)和量詞(quantifiers),其中重點(diǎn)介紹對這些概念的一些擴(kuò)展應(yīng)用,例如子模式中的非捕獲子模式,量詞匹配時(shí)的greedy與ungreedy。
子模式(subpatterns)與逆向引用(Back references)
正則表達(dá)式可以包含多個(gè)字模式,子模式由圓括號(hào)定界,可以嵌套。這也是兩個(gè)元字符“(”和“)”的作用。子模式可以有以下作用:
1. 將多選一的分支局部化。
例如,模式: cat(aract|erpillar|)匹配了 "cat","cataract" 或 "caterpillar" 之一,沒有圓括號(hào)的話將匹配 "cataract","erpillar" 或空字符串。
2. 將子模式設(shè)定為捕獲子模式(例如上面這個(gè)例子)。當(dāng)整個(gè)模式匹配時(shí),目標(biāo)字符串中匹配了子模式的部分可以通過逆向引用進(jìn)行調(diào)用。左圓括號(hào)從左到右計(jì)數(shù)(從 1 開始)以取得捕獲子模式的數(shù)。
注意,子模式是可以嵌套的,例如,如果將字符串 "the red king" 來和模式 /the ((red|white) (king|queen))/進(jìn)行匹配,捕獲的子串為 "red king","red" 以及 "king",并被計(jì)為 1,2 和 3 ,可以通過“1”,“2”,“3”來分別引用它們,“1”包含了“2”和“3”,它們的序號(hào)是由左括號(hào)的順序決定的。
在一些老的linux/unux工具里,子模式使用的圓括號(hào)需要用反斜線轉(zhuǎn)義,向這種(subpattern),但現(xiàn)代的工具已經(jīng)不需要了,本文中使用的例子都不進(jìn)行轉(zhuǎn)義。
非捕獲子模式(non-capturing subpatterns)
用一對括號(hào)同時(shí)完成上面提到的子模式的兩個(gè)功能有時(shí)會(huì)出現(xiàn)一些問題,例如,由于逆向引用的數(shù)目是有限的(通常***不超過9),而且經(jīng)常會(huì)遇到無需捕獲的子模式定義。這時(shí),可以在開始的括號(hào)后加上問號(hào)和冒號(hào)來表示這個(gè)子模式無需捕獲,就向下面這樣:((?:red|white) (king|queen))。
如果將“the white queen”作為模式匹配的目標(biāo)字符串,則捕獲的字串有“white queen”和“queen”,分別作為“1”和“2”,white雖然符合子模式“(?:red|white)”,但并不被捕獲。
我們前面已經(jīng)介紹過用括號(hào)與問號(hào)表示模式修正符的方法,為方便起見,如果需要在非捕獲子模式中插入模式修正符,可以把它直接放在問號(hào)和冒號(hào)之間,例如,下面兩個(gè)模式是等效的。
/(?i:saturday|sunday)/和/(?:(?i)saturday|sunday)/。
逆向引用(Back references)
前面介紹反斜線作用時(shí),已經(jīng)提到它的一個(gè)作用就是表示逆向引用,當(dāng)字符類之外的反斜線后跟一個(gè)大于0的十進(jìn)制數(shù)時(shí),它很有可能是一個(gè)逆向引用。它的含義正如它的名稱如言,它表示對它出現(xiàn)之前已經(jīng)捕獲的子模式的引用。這個(gè)數(shù)字代表了它引用的左括號(hào)在模式中出現(xiàn)的次序,我們在介紹子模式時(shí)已經(jīng)看到過逆向引用的一個(gè)例子,那里的過“1”,“2”,“3”分別表示所捕獲的***,第二,和第三個(gè)小括號(hào)定義的子模式的內(nèi)容。
值得注意的是,當(dāng)反斜線后的數(shù)字小于10時(shí),可以確定此為一個(gè)逆向引用,這樣,這個(gè)逆向引用就可以出現(xiàn)在之前有相應(yīng)數(shù)目的左圓括號(hào)被捕獲前而不會(huì)出現(xiàn)混淆,只有整個(gè)模式能提供那么多的捕獲子模式,就不會(huì)報(bào)錯(cuò)。說起來似乎很混亂,還是讓我們來看下面這個(gè)例子。把介紹子模子時(shí)舉的例子拿來修改一下,前面講過字符串 "the red king" 來和模式 /the ((red|white) (king|queen))/匹配,捕獲的子串為 "red king","red" 以及 "king",并被計(jì)為 1,2 和 3 ,現(xiàn)在把字符串,修改為" king,the red king",模式改為/3,the ((red|white) (king|queen))/,這個(gè)模式應(yīng)該也是可以匹配的。不過,并非所有的正則表達(dá)式工具都支持這種用法,安全的做法是在相應(yīng)序號(hào)的左括號(hào)之后使用與之相關(guān)的逆向引用。
需要注意的另一點(diǎn)是逆向引用的值是在目標(biāo)字符串中實(shí)際捕獲的符合子模式的字符串片段而非該子模式本本身。例如/ (sens|respons)e and 1ibility/會(huì)匹配“sense and sensibility” 和 “response and responsibility”,但不會(huì)是 "sense and responsibility"。當(dāng)被逆向引用的子模式后面有量詞從而被重復(fù)匹配了多次,逆向引用的值會(huì)以***一次匹配的值為準(zhǔn)。例如/([abc]){3}/匹配字符串“abc”時(shí),逆向引用“1”的值將是***一次匹配的結(jié)果“c”。
相信這里大家對Linux正則表達(dá)式的子模式(subpatterns)與逆向引用(Back references)已經(jīng)有所了解了,后面還有更精彩內(nèi)容。
【編輯推薦】