1.概述
捕獲組捕獲到的內容,不僅可以在正規表示式外部通過程式進行引用,也可以在正規表示式內部進行引用,這種引用方式就是反向引用。要了解反向引用,首先要了解捕獲組,關於捕獲組,參考 正則基礎之——捕獲組(capture group)。
反向引用的作用通常是用來查詢或限定重複、查詢或限定指定標識配對出現等等。
對於普通捕獲組和命名捕獲組的引用,語法如下:
普通捕獲組反向引用:\k,通常簡寫為\number
命名捕獲組反向引用:\k或者\k'name'
普通捕獲組反向引用中number是十進位制的數字,即捕獲組的編號;命名捕獲組反向引用中的name為命名捕獲組的組名。
2.反向引用匹配原理
捕獲組(expression)在匹配成功時,會將子表示式匹配到的內容,儲存到記憶體中乙個以數字編號的組裡,可以簡單的認為是對乙個區域性變數進行了賦值,這時就可以通過反向引用方式,引用這個區域性變數的值。乙個捕獲組(expression)在匹配成功之前,它的內容可以是不確定的,一旦匹配成功,它的內容就確定了,反向引用的內容也就是確定的了。
反向引用必然要與捕獲組一同使用的,如果沒有捕獲組,而使用了反向引用的語法,不同語言的處理方式不一致,有的語言會拋異常,有的語言會當作普通的轉義處理。
3.舉例說明一
源字串:abcdebbcde
正規表示式:([ab])\1
對於正規表示式「([ab])\1」,捕獲組中的子表示式「[ab]」雖然可以匹配「a」或者「b」,但是捕獲組一旦匹配成功,反向引用的內容也就確定了。如果捕獲組匹配到「a」,那麼反向引用也就只能匹配「a」,同理,如果捕獲組匹配到的是「b」,那麼反向引用也就只能匹配「b」。由於後面反向引用「\1」的限制,要求必須是兩個相同的字元,在這裡也就是「aa」或者「bb」才能匹配成功。
考察一下這個正規表示式的匹配過程,在位置0處,由「([ab])」匹配「a」成功,將捕獲的內容儲存在編號為1的組中,然後把控制權交給「\1」,由於此時捕獲組已記錄了捕獲內容為「a」,「\1」也就確定只有匹配到「a」才能匹配成功,這裡顯然不滿足,「\1」匹配失敗,由於沒有可供回溯的狀態,整個表示式在位置0處匹配失敗。
正則引擎向前傳動,在位置5之前,「([ab])」一直匹配失敗。傳動到位置5處時,,「([ab])」匹配到「b」,匹配成功,將捕獲的內容儲存在編號為1的組中,然後把控制權交給「\1」,由於此時捕獲組已記錄了捕獲內容為「b」,「\1」也就確定只有匹配到「b」才能匹配成功,滿足條件,「\1」匹配成功,整個表示式匹配成功,匹配結果為「bb」,匹配開始位置為5,結束位置為7。
擴充套件一下,正規表示式「([a-z])\1」也就表達連續三個相同的小寫字母,「([a-z])\1+」表示連續的n個相同的小寫字母。
4.舉例說明二
詳細的分析討論參考:正規表示式正向預搜尋的問題。
源字串:aaa bbbb ffffff 999999999
正規表示式:(\w)((?=\1\1\1)(\1))+
測試**:
string test = "aaa bbbb ffffff 999999999";
regex reg = new regex(@"(\w)((?=\1\1\1)(\1))+");
matchcollection mc = reg.matches(test);
foreach (match m in mc)
//輸出
匹配結果:bb 匹配開始位置:4
匹配結果:ffff 匹配開始位置:9
匹配結果:9999999 匹配開始位置:16
匹配結果分析:
正規表示式(\w)((?=\1\1\1)(\1))+從匹配結果上分析,其實就等價於(\w)(\1)*(?=\1\1\1)(\1),這個會相對好理解一些,下面討論下分析過程。
因為「+」等價於「」,表示至少匹配1次,下面把子表示式「((?=\1\1\1)(\1))+」展開來看下規律,下表中的「次數」表示子表示式「((?=\1\1\1)(\1))+」匹配成功的次數 。
次數
等價表示式
1
(\w)((?=\1\1\1)(\1))
2
(\w)((?=\1\1\1)(\1))((?=\1\1\1)(\1))
3
(\w)((?=\1\1\1)(\1))((?=\1\1\1)(\1))((?=\1\1\1)(\1))
…
如果最後乙個「((?=\1\1\1)(\1))」匹配成功,那麼中間的「((?=\1\1\1)(\1))」一定可以匹配成功,所以中間的限制條件(?=\1\1\1)就沒有意義了,這時就可以簡寫為「(\1)」,也就是
次數
等價表示式
1
(\w)((?=\1\1\1)(\1))
2
(\w)(\1)((?=\1\1\1)(\1))
3
(\w)(\1)(\1)((?=\1\1\1)(\1))
…
可以歸納為等價於
(\w)(\1)*((?=\1\1\1)(\1))
因為「((?=\1\1\1)(\1))」開始和結尾的()原來是用作量詞+修飾範圍的,這裡已經沒有什麼意義了,所以表示式最後可以歸納為等價於
(\w)(\1)*(?=\1\1\1)(\1)
分析這個表示式就容易多了。「(\w)」匹配乙個字元,佔一位,「\1」是對「\w」匹配內容的引用,「(\1)*」可以匹配0到無窮多個「(\w)」匹配到的字元,「(?=\1\1\1)(\1)」只佔一位,但是「(?=\1\1\1)」要求所在位置右側有三個連續相同的「(\w)」匹配到的字元,所以在「(?=\1\1\1)」這個位置右側應該有三個字元,不過只有這個位置右側的乙個字元計入最後的匹配結果,最後兩個只作為限制條件,不計入最後的匹配結果 。
以「999999999」為例,第乙個「9」由「(\w)」匹配,第二到第六個「9」由「(\1)*」來匹配,第七個「9」由「(?=\1\1\1)(\1)」中最後的「(\1)」來匹配,而第
七、八、九這三個「9」是用來保證滿足「(?=\1\1\1)」這個條件的。
詳細描述參考:正則基礎之——反向引用
正規表示式反向引用
微軟關於正規表示式的反向引用的官方文件 1 第1個 代表任意字元,後面的 代表 前面的任意字元有0個或多個 第2個 也代表任意字元,但它被括號括起來了,括號代表它 獲了,相當於被複製了,還沒被貼上 第3個 也代表任意字元,後面的 代表 前面的任意字元有0個或多個 第1個 代表轉譯符,這個符號不能直接...
表示式反向解析 正規表示式 反向引用
分組不僅用在匹配結果中,也可以在匹配的正規表示式中使用分組匹配的結果,這種功能稱為反向引用 backreference 當待匹配的字串中有些子字串出現多次的話,正規表示式模式可以將第乙個出現的子字串儲存在分組中,在模式的後面可以直接引用第乙個匹配的結果。因為分組即可通過索引也可以通過名字來訪問,所以...
正規表示式的反向引用
其實,小括號包含的表示式所匹配到的字串 不僅是在匹配結束後才可以使用,在匹配過程中也可以使用。表示式後邊的部分,可以引用前面 括號內的子匹配已經匹配到的字串 引用方法是 加上乙個數字。1 引用第1對括號內匹配到的字串,2 引用第2對括號內匹配到的字串 以此類推,如果一對括號內包含另一對括號,則外層的...