快速開始
教程
工具與語言
範例
參考
書評
正則表達式教程
介紹
目錄
特殊字符
不可見字符
正則引擎內部
字符類
字符類減法
字符類交集
速記字符類
錨點
單詞邊界
替換
可選項目
重複
分組和捕獲
反向引用
反向引用,第2部分
命名組
相對反向引用
分支重置組
自由間隔和注釋
Unicode
模式修飾符
原子分組
佔有量詞
先行斷言和後行斷言
環繞,第2部分
保持文本不匹配
條件
平衡組
遞歸
子程序
無限遞歸
遞歸和量詞
遞歸和捕獲
遞歸和反向引用
遞歸和回溯
POSIX括號表達式
零長度匹配
持續匹配
本站更多資訊
介紹
正則表達式快速入門
正則表達式教程
替換字符串教程
應用與語言
正則表達式示例
正則表達式參考
替換字符串參考
書評
可打印的PDF
關於本站
RSS訂閱和博客
RegexBuddy—Better than a regular expression tutorial!

對失敗組的反向引用

前一主題反向引用適用於所有正則表達式風格,除了那些根本不支援反向引用的少數風格。當您開始做一些不符合“匹配以前捕獲組所匹配的文本”的工作時,風格會表現出不同的行為。

反向引用到一個未匹配任何內容的捕獲組和到根本沒有參與匹配的捕獲組之間存在區別。正則表達式 (q?)b\1 匹配 bq? 是可選的,並且不匹配任何內容,導致 (q?) 成功匹配並捕獲空內容。 b 匹配 b,而 \1 成功匹配捕獲組捕獲的空內容。

在大多數情況下,正則表達式(q)?b\1無法匹配b(q)根本無法匹配,因此該組永遠無法捕獲任何內容。由於整個組是可選的,引擎確實繼續匹配b。 現在引擎到達\1,它引用了一個根本沒有參與匹配嘗試的組。這導致回溯引用根本無法匹配,模擬組的結果。由於沒有?使\1成為可選的,因此整體匹配嘗試失敗。

少數例外之一是JavaScript。根據官方的ECMA標準,對於一個未參與捕獲的組的回溯引用,必須成功地匹配空值,就像對於一個捕獲了空值的參與組的回溯引用一樣。換句話說,在JavaScript中,(q?)b\1(q)?b\1都匹配bXPath也是這樣工作的。

std::regex的Dinkumware實現對於支持回溯引用的所有語法都像JavaScript一樣處理回溯引用。直到版本1.46,Boost也是如此。從版本1.47開始,Boost在使用ECMAScript語法時無法回溯引用未參與的組,但在使用基本和grep語法時仍然可以讓它們成功匹配空值。

對不存在的捕獲組的回溯引用

在大多數正則表達式的情況下,對不存在的組的回溯引用,例如(one)\7,都是一個錯誤。不過,也有例外情況。JavaScript\1\7視為八進制轉義,當正則表達式中的捕獲組少於反斜杠後的數字時。\8\9是一個錯誤,因為8和9不是有效的八進制數字。

Java將對不存在的組的回溯引用視為對存在但從未參與匹配的組的回溯引用。它們不是一個錯誤,而只是從未匹配任何內容。

.NET稍微複雜一些。 .NET支持單位和雙位回溯引用,以及沒有前導零的雙位八進制轉義。回溯引用優先於八進制轉義。因此,在正則表達式中少於12個捕獲組的情況下,\12是一個換行符(八進制12 = 十進制10)。在正則表達式中有12個或更多捕獲組的情況下,它將是第12個組的回溯引用。 .NET不支持單位八進制轉義。因此,在正則表達式中少於7個捕獲組的情況下,\7

向前參照

許多現代正規表達式(regex)引擎,包括JGsoft.NETJavaPerlPCREPHPDelphi以及Ruby,都允許使用向前參照。這使您可以在正規表達式中使用對稍後出現的群組的反向引用。向前參照顯然只在它們位於重複的群組內時才有用。然後可能出現正規表達式引擎在群組已經匹配之後才評估反向引用的情況。在嘗試群組之前,反向引用就像對失敗的群組的反向引用一樣失敗。

如果支援向前參照,正規表達式(\2two|(one))+會匹配oneonetwo。在字符串的開頭,\2失敗。嘗試其他選項one被第二捕獲群組匹配,然後被第一群組匹配。然後重複第一群組。這次,\2匹配由第二群組捕獲的one。然後two匹配two。通過兩次重複第一群組,正規表達式已經匹配整個主題字符串。

JavaScript不支援向前參照,但不將其視為錯誤。在JavaScript中,向前參照總是找到零長度匹配,就像JavaScript中對未參與的群組的反向引用一樣。因為這不是特別有用的,XRegExp將它們視為錯誤。在std::regexBoostPythonTclVBScript中,向前參照是一種錯誤。

嵌套引用

嵌套參考是捕獲組內部的反向參考。與向前參考一樣,只有在重複的組內部才有用,例如 (\1two|(one))+。當支持嵌套參考時,此正則表達式還匹配 oneonetwo。在字符串開頭,\1 失敗。嘗試其他替代方案,第二捕獲組匹配 one,然後由第一組捕獲。然後再次重複第一組。這一次,\1 匹配由第一組上一次退出時捕獲的 one。正則引擎重新進入第一組不重要。組匹配的文本在組之前退出時存儲到反向參考中。然後,two 匹配 two。通過兩次重複第一組,正則表達式已經匹配了整個主題字符串。如果在匹配後檢索捕獲組的文本,第一組存儲 onetwo,而第二組捕獲了字符串中第一個 one 的出現。

JGsoft.NETJavaPerlVBScript 都支持嵌套參考。 PCRE 也支持,但在具有嵌套反向參考的捕獲組中存在回溯錯誤。PCRE 8.01 沒有修復這些錯誤,而是通過強制嵌套參考的捕獲組為 原子組 來繞過這些錯誤。因此,在PCRE中,(\1two|(one))+(?>(\1two|(one)))+ 是相同的。這影響基於PCRE的正則引擎的語言,例如 PHPDelphiR

JavaScriptRuby 不支持嵌套參考,但將其視為對非參與組的反向參考而不是錯誤。在JavaScript中,這意味著它們始終匹配零長度字符串,而在Ruby中,它們始終無法匹配。在 std::regexBoostPythonTcl 中,嵌套參考是一個錯誤。