正則表達式學習筆記(三)

  • 後向引用

說明後向引用的之前,先對分組進行更一步的學習。

前面說過,用小括號括起來就是一個分組,或者叫子表達式,但是,其實分組並不是表面那麼簡單,有如下幾條:

(1)       分組其實是有組號的。

從左到右,第一個分組組號爲1,第二個組號爲2,依次遞增,分組0則對應整個正則表達式。

(2)       分組的組號分配是有規則的。

實際上組號分配過程是從左往右掃兩遍:第一遍給未命名組分配,第二遍只給命名組分配,這樣導致的結果就是所有命名組的組號大於爲命名組的組號。

(3)       分組的組號分配這個權利是可以被剝奪的。

怎麼剝奪?使用(?:exp)這樣的語法。

         說完了分組,有個疑問,分組還要弄組號這是做什麼?還搞的這麼麻煩。

         答案就是,分組的組號是可以在正則表達式中使用的,比如說爲了這個後向引用。

         舉個例子:如果你想要重複搜索前面某個分組匹配的文本怎麼辦?難道又重新寫一遍分組?這裏,就可以使用後向引用了。

         請看例子:\b(\w+)\b\s+\1\b

         這個表達式可以這樣分解:

                            \b(\w+)\b \s+ \1\b

可以看到:我們要匹配的字符串是一個單詞(至少一個字符),中間有至少有一個空白符,然後\1表示組號,即重複前面那個分組表示的單詞。

         這個正則表達式可以用來搜尋什麼move move之類的。

         再來重複一次後向引用:用於重複搜索前面出現的某個分組。

         關於分組的組名,這裏在多說幾句。一個分組的組名是可以人爲命名的。

         使用語法:(?<word>\w+)

         把尖括號改成也可以(?’word’\w+),這樣\w+分組的組名就是word了。

         要是想要後向引用這個分組匹配的文本怎麼辦?

         可以使用\k<word>,例如:將\b(\w+)\b\s+\1\b寫成\b(?<Word>\w+)\b\s+\k<Word>\b

         小括號這個元字符的作用很多,與之相關的語法小結一下:

分類

語法

詳解

捕獲

(exp)

分組

(?<name>exp)

分組到名爲“name“的分組裏,與<?’name’exp>

(?:exp)

匹配exp,但是不捕獲該文本,也不分配組號

零寬斷言

(?=exp)

匹配exp前面的位置

(?<=exp)

匹配exp後面的位置

(?!exp)

匹配後面跟着的不是exp的位置

(?<!exp)

匹配前面不是exp的位置

註釋

(?#comment)

註釋

  • 零寬斷言

解釋下上述表裏面的零寬斷言部分的四條語法。

相信已經從表裏面讀到了,零寬斷言是用來查找某些內容之前或者之後的東西,他們指定了一個位置,這個位置應該滿足一定的條件(斷言)。下面依次解釋:

1(?=exp)

         叫做零寬度正預測先行斷言。

         舉例:\b\w+(?=ing\b)

         解析:匹配以ing結尾的單詞的文本並捕獲出來,不包括ing

wKioL1V1O7bw16OlAABEO9oKfoE426.jpg

2(?<=exp)

         叫做零寬度正回顧後發斷言。

         舉例:(?<=\bre)\w+\b

         解析:匹配以re開頭的單詞的後部分,不包括re

wKioL1V1O6rQrIcPAABBj7BFxpE784.jpg

3(?!exp)

叫做零寬度負預測先行斷言。

舉例:\d{3}(?!\d)

解析:匹配3個數字,但是3個數字後面不能是數字。

wKiom1V1OfqiRtz7AABKEPKLoKM993.jpg

4(?<!exp)

         叫做零寬度負回顧後發斷言。

         舉例:(?<![a-z])\d{7}

         解析:前面不是小寫字母的7個數字。

wKiom1V1OeLAGoN_AABRaFucGpE198.jpg

34項都屬於負向零寬斷言。

這裏看一個複雜的正則表達式:

舉例:(?<=<(\w+)>).*(?=<\/\1>)

解析:匹配不包含屬性的簡單HTML標籤內裏的內容

(<?(\w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是<b>),然後是.*(任意的字符串),最後是一個後綴(?=<\/\1>)。注意後綴裏的\/,它用到了前面提過的字符轉義;\1則是一個反向 引用,引用的正是捕獲的第一組,前面的(\w+)匹配的內容,這樣如果前綴實際上是<b>的話,後綴就是</b>了。整個表達式匹配的是<b></b> 之間的內容(再次提醒,不包括前綴和後綴本身)。這個例子就是第一個語法和第二個語法的結合。

  • 註釋

       註釋的語法我們已經知道:(?#comment),可以插入到正則表達式的任一個位置。唯一需要說明的是,使用註釋的時候,最好能夠啓用“忽略模式裏的空白符“,這樣在寫註釋的時候就可以換行了。

  • 處理選項

處理選項,在PHP裏面即是模式修飾符,作用就是設定模式。也就是規定了正則表達式如何解釋和應用。不同的語言這個處理選項是不同的,這裏主要說一說PHP裏面的主要的模式。

修飾符

表達式寫法

詳解

I

(?i)…(?-i)(?i:..)

忽略大小寫模式

M

(?m)…(?-m)(?m:..)

多文本模式,即字符串內有多個換行符,影響^$作用

s

(?s)…(?-s)(?s:..)

但文本模式,在此模式下,元字符點.可以匹配換行符

X

(?x)…(?-x)(?x:..)

忽略空白字符

模式修飾符既可以寫在正則表達式的外面,也可以寫在表達式內。

例如:

忽略大小寫:

wKioL1V1O1GhkJNKAABIi4YLEgs249.jpg

        


  • 貪婪和懶惰

         正則表達式裏面有重複選擇的元字符,例如*等,包含了這種玩意的正則表達式往往會匹配儘可能多的字符,這被稱作貪婪匹配。

         例如:a.*c

         面對acacaac這樣的字符串,返回的結果是acacaac,而不會是ac或者aac

wKioL1V1O3PBU1O7AAAlJQT19lI130.jpg

與上面相反,假設要是想要匹配儘量少的字符,這就被稱作爲懶惰。

舉例:根據前面的a.*c,在.*後面加上?。

         即爲:a.*?c

wKiom1V1OcHBm8KoAAAstxLcDyw093.jpg

另外,根據上圖,有點需要說明的是,懶惰和貪婪的規則優先級屈尊與這一條規則之下:最先開始的匹配擁有最高的優先權。所以在上面字符串acacaac的後面三個字符串aac共同構成了一個捕獲文本,而不是ac(即倒數一二個)。

下面總結下懶惰限定符作用在重複次數上的作用:

語法

詳解

*?

重複任意次,但是儘可能少。

+?

重複一次或者更多,但是儘可能少。

??

重複0次到1次,儘可能少。

{n,m}?

重複nm次,儘可能少。

{n,}?

重複n次,儘可能少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章