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

無限遞迴

例如 (?R)?za?(?R)?za|(?R)z 這些正規表示式在沒有任何必須在遞迴之前比對的項目下使用遞迴,可能會導致無限遞迴。如果正規表示式引擎在未前進文字的情況下到達遞迴,那麼下一個遞迴將再次在未前進文字的情況下到達遞迴。對於第一個正規表示式,這會在比對嘗試開始時立即發生。對於其他兩個,這會在沒有更多字母 a 可以比對時發生。

JGsoft V2 和 Boost 1.64 將前兩個正規表示式視為語法錯誤,因為它們總是會導致無限遞迴。它們允許第三個正規表示式,因為它可以比對 a。Ruby 1.9 和更新版本、所有版本的 PCRE,以及 PCRE2 10.20 和更早版本將所有三種形式的潛在無限遞迴視為語法錯誤。Perl、PCRE2 10.21 和更新版本,以及 Boost 1.63 和更早版本允許所有三種形式。

循環無限子常式呼叫

子常式呼叫也可能導致無限遞迴。所有版本都以處理整個正規表示式潛在無限遞迴的方式來處理 ((?1)?z)(a?(?1)?z)(a|(?1)z) 中的潛在無限遞迴。

但是,如果它們呼叫的群組有另一個子常式呼叫,呼叫第一個子常式呼叫的父群組,那麼本身並非遞迴的子常式呼叫最終可能會變成遞迴。當子常式呼叫被迫繞圈圈時,也會導致無限遞迴。在編譯正規表示式時偵測這種循環呼叫比檢查直接無限遞迴更複雜。只有 JGsoft V2 和 Ruby 1.9 及更新版本能夠偵測這種情況並將其視為語法錯誤。所有其他版本都允許這些正規表示式。

錯誤和崩潰

當發生無限遞迴時,無論是直接遞迴還是子常式呼叫繞圈圈,JGsoft V2、Perl 和 PCRE2 都將其視為比對錯誤,並中止整個比對嘗試。Boost 1.64 透過不嘗試遞迴並假裝遞迴失敗來處理這個問題。如果遞迴是可選的,那麼 Boost 1.64 可能會找到其他版本會擲回錯誤的比對。

當發生無限遞迴時,Boost 1.63 和更早版本,以及 PCRE 8.12 和更早版本會崩潰。這也影響了 Delphi(最高版本為 XE6)和 PHP(最高版本為 5.4.8),因為它們基於較舊的 PCRE 版本。

無限遞迴

一個正則表示式,例如 a(?R)z,具有非選項的遞迴標記,且沒有 備選方案(沒有相同的遞迴),會導致無窮遞迴。此類正則表示式永遠找不到匹配項。當 a 匹配時,正則表示式引擎會嘗試遞迴。如果它可以匹配另一個 a,則必須再次嘗試遞迴。最後,a 將用完要匹配的字母。然後遞迴失敗。由於它不是選項,因此正則表示式無法匹配。

編譯您的正則表示式時,JGsoft V2 和 Ruby 會偵測到此情況。它們將無窮遞迴標記為語法錯誤。Perl、PCRE、PCRE2 和 Boost 偵測不到無窮遞迴。它們只會執行匹配程序,而找不到任何匹配項。