注意:Crystal 正在升級其正規表示式引擎
Crystal 自創立以來就使用 PCRE 函式庫來處理正規表示式。這個函式庫有兩個主要版本,而 Crystal 目前使用第一個版本 (PCRE)。然而,這個版本已達到生命週期終點。因此,對於下一個版本 (1.8),我們計畫遷移到其後繼版本 PCRE2。
PCRE 與 PCRE2
PCRE 和 PCRE2 這兩個函式庫版本彼此大多相容。有些小的差異可能會導致重大變更。但我們預期不會有太多障礙。最值得注意的是,在某些邊緣情況下,PCRE2 比 PCRE 更嚴格。這表示 PCRE 可能會接受某些無效的正規表示式,但 PCRE2 不會允許它們。
不幸的是,沒有指南可以幫助移植。最完整的變更清單是 Stackoverflow 上的這個討論串。
從好的方面來看,PCRE2 擴展了對有趣功能的支持。您可以閱讀這篇 維基百科文章或專案文件,了解更多關於其功能的資訊。
正規表示式字面值的驗證
為了理解以下路線圖,重要的是要建立編譯器和 stdlib 之間關於正規表示式的現有差異。當您編寫類似 /(a|b)*/.match "abba"
的程式碼時,編譯器會檢查正規表示式字面值 (/(a|b)/
) 的有效性。無效的運算式將導致語法錯誤。然後,當執行程式時,與正規表示式函式庫的 stdlib 綁定會執行實際的匹配。
這種差異有一個結果:可以使用一個函式庫檢查正規表示式字面值,然後使用另一個函式庫執行它們。
在最後一個版本 (1.7) 中,我們已經新增了使用編譯器標記選擇加入 stdlib 中的 PCRE2 的可能性。這表示如果您在系統中安裝了 1.7 和 PCRE2,您可以使用 -Duse_pcre2
編譯程式或 shard,然後執行它來查看是否有任何正規表示式在執行階段失敗。如果正規表示式失敗,則必須重寫它以符合 PCRE2。
在即將發布的版本中,編譯器和 stdlib 預設將使用 PCRE2。如果發生任何問題,仍然可以使用編譯器標記 -Duse_pcre
在 stdlib 中使用 PCRE。但是編譯器將始終使用 PCRE2 來驗證正規表示式字面值。這對於一致性非常重要,因為它直接影響 Crystal 的語法。
如果您需要繼續使用舊的 PCRE,並且編譯器因為 PCRE2 的限制而認為字面值無效,您可以將字面值轉換為接收運算式作為字串字面值的 Regex.new
呼叫。基於效能考量,建議快取 Regex
執行個體 (例如,在常數中)。
將您的專案遷移到 PCRE2
距離 1.8 版本還有一個多月的時間,這讓我們有時間將變更引入每日建置,並讓社群測試其 shards 和專案是否存在不相容性。
因此,為了做好準備,我們建議您
-
如果您使用的是 1.7,請使用編譯器標記
-Duse_pcre2
來檢查您的專案的執行情況。 -
如果您使用的是每日建置,它們已經使用 PCRE2。要取得舊的行為,您需要新增
-Duse_pcre
(請記住,這只會影響執行階段行為,而不是語法或正規表示式字面值)。 -
修正任何導致問題的正規表示式 (如果有的話)。
-
如果您在 2 中新增了
-Duse_pcre
,請移除它:1.9 之後將不保證支援 PCRE。
如果您的專案因為此變更而失敗,請隨時告訴我們。我們會收集資訊並分享常見問題的修正程式。
請最晚在 1.8 中切換到 PCRE2。