[翻譯]正則引擎的幾種分類

原文鏈接http://www.softec.lu/site/RegularExpressions/RegularExpressionEngines

正則表達式引擎是正則表達式匹配算法的基礎。其有多種不同的實現,但大多數都是基於Henry Spencer的NFA引擎。

正則引擎有兩個大分類,DFA和NFA,像Perl、Java、.Net、PHP、Python、Ruby……等大多是工具都是用了NFA引擎。少數廣泛被使用的工具如mawk使用了POSIX NFA引擎(NFA的一種變種)。以高效著稱的工具採用了更爲高效的DFA引擎。諸如GNU awk,GNU egrep和Tcl之類的一些工具結合了NFA / DFA兩種引擎,將兩者的優點結合在一起。

基於不同類型引擎的實現的正則表達式,主要有以下幾點差異。

  • 語法
  • 匹配內容
  • 零寬斷言(環視) 功能
  • 捕獲功能
  • 性能

所有的引擎都會對文本做從左向右的最長匹配,但具體細節取決於使用了何種引擎。

傳統的NFA引擎

NFA引擎中使用的非確定有限狀態機(Nondeterministic finite automation)是一種由要匹配的表達式驅動的算法。這使得正則表達式像一個小的編程語言一樣,可控制引擎在匹配失敗時候的行爲。

正則引擎從正則表達式其實位置開始,嘗試正則表達式與文本的開頭進行匹配,如果匹配成功,都前進一個配置,否則文本一直前進到下一個字符,直到匹配。 如果正則表達式需要作出選擇(例如使用替代詞或可選的量詞),它將選擇其中之一,並記住其他選擇以及在文本中進行選擇的位置。如果在之後的處理中,匹配失敗,並且還有其他可選的路徑,則引擎將回溯做之前作出選擇的位置,並嘗試其他的選擇。如果沒有其他可用的替代方案,則匹配失敗,引擎前進到下一個字符並從頭開始匹配正則表達式。

如果引擎到達了正則表達式的末尾並且所有內容都已匹配,則引擎就會認爲匹配成功,並最終放棄所有剩下的替代方法,甚至不再繼續探索。這裏有很重要的一點:選擇不同路徑的順序很重要,它決定是是否能做到最長匹配。

引擎會真正按照正則表達式進行匹配,讓你選擇達到完全匹配所需的每個步驟。你必須很謹慎地告訴它,首先檢查哪種選擇才能達到您的期望。你也有機會調整正則表達式,以最大程度地減少回溯並儘早進行匹配。 NFA引擎中使用的方法的一些示例也可以幫助你瞭解回溯是如何工作的。

POSIX NFA 引擎

POSIX NFA引擎類似於傳統NFA引擎,但是當找到成功的匹配項時,它將會記錄匹配結果,並且嘗試其他可用的替代方法以查找是否可以找到更長的最左邊的匹配。 這消除了傳統NFA引擎中不能保證最長最左匹配的問題。

以弗裏德爾(Friedl)的書中的這個有趣的例子爲例:用one(self)?(selfsufficient)? 去匹配oneselfsufficient,傳統的NFA將匹配 oneself,而POSIX NFA將匹配oneselfsufficient,因爲(self)?有兩種選擇,匹配self或者啥都不匹配,顯然最終匹配到的更長。

DFA引擎

DFA引擎中使用的確定性有限自動機(Deterministic finite automaton)是一種由要搜索的文本驅動的算法。 對於搜索到的文本中的每個字符,DFA引擎只會查看一次。 實際上,它相當於並行嘗試了NFA中所有可能的替代方法,並將返回其中最長的匹配。

這種方法確實更高效,但也有很多缺點:

  • 你無法控制表達式返回匹配項的方式,無論您如何構造表達式,它始終將返回最長最左匹配。
  • 沒有回溯,因此所有重複的運算符都是貪婪的。 原子分組和所有格修飾符也是無稽之談。 (更多詳細信息,請查閱RegularExpressionsBacktracking
  • 不支持零寬斷言(環視)
  • 捕獲和反向引用也不可能實現
  • 正則表達式預編譯時間更長,佔用更多內存

NFA和DFA混合引擎

由於DFA引擎速度快,但NFA引擎的功能多,因此,混合NFA / DFA引擎試圖將二者的優勢結合起來。 迄今爲止唯一可用的完全混合實現是Tcl中使用的Henry Spencer引擎,它是對原始實現的完全重寫。 像GNU egrep和awk只是將兩個獨立的引擎放一起,然後根據是否使用了NFA特有的功能決定使用哪個引擎。

本文來自https://blog.csdn.net/xindoo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章