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

原子群組

原子群組是一種群組,當 regex 引擎離開它時,會自動捨棄群組內任何標記所記住的所有回溯位置。原子群組是非擷取的。語法為 (?>group)環顧群組也是原子的。原子群組受到大多數現代正規表示式風格支援,包括 JGsoft 風格、JavaPCRE.NETPerlBoostRuby。其中大多數也支援 佔有量詞,這基本上是原子群組的符號便利性。Python 從 Python 版本 3.11 開始支援原子群組和佔有量詞。

一個範例將使原子群組的行為變得清楚。正規表示式 a(bc|b)c(擷取群組)比對 abccabc。正規表示式 a(?>bc|b)c(原子群組)比對 abcc 但不比對 abc

應用於 abc 時,兩個正規表示式都會將 a 比對到 abc 比對到 bc,然後 c 會無法比對到字串結尾。在這裡,它們的路徑開始分歧。具有擷取群組的正規表示式已記住交替的回溯位置。群組會放棄其比對,b 接著比對到 bc 比對到 c。找到比對!

然而,具有原子群組的正規表示式在比對到 bc 之後,會從原子群組中退出。在那個時間點,群組內部所有記號的回溯位置都會被捨棄。在此範例中,交替選項會嘗試在字串的第二個位置比對 b,但這個選項會被捨棄。因此,當 c 失敗時,正規表示式引擎沒有其他可嘗試的替代方案。

當然,上述範例並不是很實用。但它確實非常清楚地說明原子群組如何消除特定比對。或者更重要的是,它消除了某些比對嘗試。

使用原子群組進行正規表示式最佳化

考慮正規表示式 \b(integer|insert|in)\b 和主旨 integers。很明顯,由於 字首字尾界線,這些不會比對到。不太明顯的是,正規表示式引擎會花費相當多的精力來找出這一點。

\b 在字串開頭比對,而 integer 比對 integer。正規表示式引擎會記住群組中還有兩個備選項,並繼續比對 \b。這無法在 rs 之間比對。因此,引擎會回溯嘗試群組內的第二個備選項。第二個備選項比對 in,但無法比對 s。因此,引擎會再次回溯到第三個備選項。 in 比對 in\b 這次無法在 nt 之間比對。正規表示式引擎沒有記住更多回溯位置,因此宣告失敗。

要找出 integers 不在我們的字詞清單中,需要做很多工作。我們可以透過告訴正規表示式引擎,如果在比對 integer 後無法比對 \b,就不應該嘗試其他字詞,來最佳化這一點。我們在主旨字串中遇到的字詞較長,而且不在我們的清單中。

我們可以將擷取群組轉換為原子群組來做到這一點: \b(?>integer|insert|in)\b。現在,當 integer 比對時,引擎會退出原子群組,並丟棄為交替儲存的回溯位置。當 \b 失敗時,引擎會立即放棄。在掃描大型檔案尋找長關鍵字清單時,可以大幅節省時間。當你的備選項包含會導致 災難性回溯重複代碼(更不用說重複群組)時,這種節省至關重要。

不要急於將所有群組設為原子群組。正如我們在上面的第一個範例中所見,原子群組也會排除有效的比對。比較 \b(?>integer|insert|in)\b\b(?>in|integer|insert)\b 套用於 insert 時的行為。前者正規表示式比對成功,而後者失敗。如果群組不是原子群組,兩個正規表示式都會比對成功。請記住,交替 會從左到右嘗試其備選項。如果第二個正規表示式比對 in,它不會因為原子群組而嘗試其他兩個備選項。