快速入門
教學
工具和語言
範例
參考
書籍評論
正則表達式教學
簡介
目錄
特殊字元
非列印字元
正則表達式引擎內部
字元類別
字元類別減法
字元類別交集
簡寫字元類別
錨點
字詞邊界
交替
選用項目
重複
分組和擷取
反向參照
反向參照,第 2 部分
命名群組
相對反向參照
分支重設群組
自由間距和註解
Unicode
模式修改器
原子群組
佔有量詞
前瞻和後顧
環顧,第 2 部分
將文字排除在比對之外
條件
平衡群組
遞迴
子常式
無限遞迴
遞迴和量詞
遞迴和擷取
遞迴和反向參照
遞迴和回溯
POSIX 方括號表達式
零長度比對
持續比對
本網站的更多內容
簡介
正則表達式快速入門
正則表達式教學
替換字串教學
應用程式和語言
正則表達式範例
正則表達式參考
替換字串參考
書籍評論
可列印 PDF
關於本網站
RSS 資訊和部落格
RegexBuddy—Better than a regular expression tutorial!

遞迴中的量詞

遞迴簡介顯示 a(?R)?z 如何比對 aaazzz量詞 ?使前一個代幣成為選用。換句話說,它重複代幣 0 到 1 次。在 a(?R)?z 中,(?R) 由其後面的 ? 變成選用。您可能會疑惑,為什麼正則表達式嘗試遞迴三次,而不是一次或根本不嘗試。

原因是,在遞迴時,正則表達式引擎會重新開始嘗試整個正則表達式。除了引擎會在字串中前進之外,所有量詞和選項的行為就像遞迴之前的比對程序從未發生過一樣。正則表達式引擎會在退出遞迴時還原所有量詞和選項的狀態,無論遞迴是否比對成功。基本上,比對程序會正常繼續,就像遞迴從未發生過一樣,除了引擎會在字串中前進之外。

如果您熟悉程序設計語言,正則表達式遞迴基本上是一個遞迴函式呼叫,而量詞是函式中的局部變數。函式的每個遞迴都會取得自己的局部變數集,這些變數不會影響堆疊中較高層級的遞迴中的相同局部變數,也不會受到這些變數影響。遞迴中的量詞在所有版本中都是這樣運作的,Boost 除外。

讓我們看看 a(?R){3}z|q 的行為(Boost 除外)。最簡單的可能配對是 q,由正規表示式的第二個選項找到。

第一個選項配對的最簡單配對是 aqqqz。在 a 配對後,正規表示式引擎開始遞迴。 a 無法配對 q。引擎仍在遞迴中,嘗試第二個選項。 q 配對 q。引擎以成功的配對退出遞迴。引擎現在注意到量詞 {3} 已成功重複一次。它需要再重複兩次,因此引擎開始另一個遞迴。它再次配對 q。在量詞的第三次迭代中,第三次遞迴配對 q。最後,z 配對 z,找到整體配對。

這個正規表示式不配對 aqqzaqqqqzaqqz 失敗,因為在量詞的第三次迭代中,遞迴無法配對 zaqqqqz 失敗,因為在 a(?R){3} 已配對 aqqq 之後,z 無法配對第四個 q

正規表示式可以配對較長的字串,例如 aqaqqqzqz。對於這個字串,在量詞的第二次迭代中,遞迴配對 aqqqz。由於每個遞迴都分別追蹤量詞,因此遞迴需要連續三次遞迴才能滿足量詞的自身實例。這可能導致任意長的配對,例如 aaaqqaqqqzzaqqqzqzqaqqaaqqqzqqzzz

Boost 如何處理遞迴中的量詞

Boost 對量詞在遞迴中的運作方式有自己的想法。遞迴僅在 Boost 中與其他版本中相同,如果遞迴運算子完全沒有量詞,或者如果它有 * 作為其量詞。任何其他量詞都可能導致 Boost 1.59 或更早版本與 Boost 1.60 及更高版本相較於其他正規表示式版本有非常不同的配對(或缺乏配對)。Boost 1.60 嘗試修復 Boost 和其他版本之間的一些差異,但它只導致不同的不相容行為。

在 Boost 1.59 及之前版本中,遞迴量詞會計算整個遞迴堆疊中的迭代和遞迴次數。因此,在 Boost 1.59 中,a(?R){3}z|q 的可能匹配項包括 aaaazzzzaaaqzzzaaqqzzaaqzqzaqaqzzz。在所有這些匹配項中,遞迴和迭代的次數加起來等於 3。其他版本不會找到這些匹配項,因為它們需要在每次遞迴期間進行 3 次迭代。因此,其他版本可以匹配類似 aaqqqzaqqqzaqqqzzaqqaqqqzz 的字串。Boost 1.59 僅會在這些字串中匹配 aqqqz

Boost 1.60 嘗試像其他版本一樣在每個遞迴層級迭代量詞,但執行方式不正確。任何使遞迴為可選的量詞都允許多次重複。因此,Boost 1.60 和更新版本會將 a(?R)?z 視為與 a(?R)*z 相同。雖然這修正了 a(?R)?z 在 Boost 1.59 中無法完全匹配 aaazzz 的問題,但它也允許其他版本無法使用此正規表示式找到的匹配項,例如 aazazz。如果量詞不是可選的,則 Boost 1.60 僅允許它在第一次遞迴期間匹配。因此,a(?R){3}z|q 只能匹配 qaqqqz

Boost 在遞迴量詞上的問題也會影響遞迴標記的父群組上的量詞。它們也會影響子常式呼叫上的量詞,以及包含子常式呼叫到具有量詞的群組的父群組的群組上的量詞。

遞迴中其他標記上的量詞

正規表示式中其他標記上的量詞在遞迴期間會正常運作。它們會在每次遞迴中分別追蹤其迭代。因此,a{2}(?R)z|q 會匹配 aaqzaaaaqzzaaaaaaqzzz 等。在每次遞迴期間,a 都必須匹配兩次。

像這樣位於遞迴中但不會重複遞迴本身的量詞在 Boost 中確實可以正確運作。