正則表達式優化

正則表達式優化
——《精通正則表達式》閱讀筆記

[TOC]

第4章:表達式的匹配原理

引擎

DFA (Deterministic Finite Automaton 確定有窮自動機):
常見的只有MySQL,文本主導,不支持反向引用和捕獲括號,但快

傳統型 NFA(Non-非):
大多數語言,表達式主導,編譯快,內存少,寫法不同有性能差異

標準 POSIX NFA:
leftmost-longest,嘗試所有確保最長

混合 Tcl 等:
Perl、Python、Go(leftmost-first)

規則

最左優先,儘可能多(匹配優先)

回溯

NFA 有兩個可能時會根據 匹配優先* 還是 忽略優先*?
走其中一個分支,並保存備用狀態
如果不成功再回溯嘗試另一個分支

第5章:正則表達式實用技巧

(多選|分支)排序可能影響匹配結果

第6章:打造高效正則表達式

減少測試和回溯

  • 如果順序不影響結果時更多匹配的放前面
  1. 編譯
  2. 傳動(從第1個字符開始,從第2個字符開始...)
  3. 檢測(相連 量詞{m,n}+* (捕獲))
  4. 成功/->2.傳動
  5. 失敗

常見措施

編譯優化

  • 緩存

傳動優化

  • 錨點(行始^ \A 起始\G 行末$ \Z \z)
  • 隱式錨點(.* .+開始)
  • 開始字符====={4}快100倍
  • 內嵌字符(Boyer-Moore字符串檢索算法後前移, 需要前面固定個數)
  • 長度小於時不運行

正則優化

  • 連接當做整體
  • .*特殊優化比(?:.)*快(Java 10% Python 50倍)
  • 消除沒必要的括號
  • 消除沒必要的[字符組]
  • 忽略優先量詞*?(儘可能少)通常比匹配優先量詞慢
  • 限制回溯,避免括號內外都是量詞
  • 避免指數級(超線性)匹配
  • 使用佔有優先量詞(+不會回溯)減少狀態
  • \d{4}量詞優化比\d\d\d\d快(Java 幾倍 Python 20%)
  • 引擎識別捕獲括號是否需要

訣竅

  • xx*x+能適應的優化更多
  • 手工模擬優化
  • (000|999)$比關閉結束錨點優化的(?:000|999)$快(Perl 幾千倍)
  • 避免重新編譯,Perl避免用變量插值
  • 使用(?:非捕獲型括號)
  • 不要濫用括號,如上面的.*(?:.)*
  • 不要濫用字符組,[.]應該用\.
  • 不區分大小寫效率低已經修正
  • 使用起始錨點.*開頭的前面加^\A
  • 從量詞中提取: xx*替代x*-----{0,2}替代-{5,7}
  • 提取開頭: th(is|at)替代(this|that)
  • 將錨點獨立出來: ^(?:abc|123)替代^abc|^123^(abc)替代(^abc)
  • 末尾獨立出$
  • 接近開頭忽略優先*?,接近結尾匹配優先
  • 拆分成多個正則
  • 使用(?>固化分組)和佔有優先量詞*+
  • 最可能匹配的分支放前面(POSIX 會全部嘗試取最長就不需要)
  • 結尾部分分散到各個部分(有些系統不需要如Perl的$)

消除循環

"(\\.|[^\\"]+)*"

優化爲:
"[^\\"]*(\\.[^\\"]*)*"

公式:
opening normal* (special normal*) closing
左 常規*(特殊 常規*)* 右
  1. 常規和特殊的開頭不能重合
  2. 特殊部分必須匹配至少一個字符
  3. 特殊部分必須是固化的

方法2:[^\\"]匹配更多,如果是轉義,後面繼續,結果一樣

方法3:匹配主機名

[a-z]+(\.[a-z]+)*

使用佔有優先量詞

"([^\\"]++|\\.)*+"

使用固化分組

"(?>(?>[^\\"]+|\\.)*)"
\G(?:^|,)(?:((?>[^"]*)(?>""[^"]*)*)|([^",]*))

消除註釋

/\*.*?\*/
/\*([^*]|\*+[^/*])*\*+/

消除循環
/\*[^*]*\*+(?:[^/*][^*]*\*+)*/

流暢運轉

塊註釋=/\*[^*]*\*+(?:[^/*][^*]*\*+)*/
行註釋=//[^\n]*
雙引號="[^\\"]*(\\.[^\\"]*)*"
單引號='[^\\']*(\\.[^\\']*)*'
(雙引號|單引號)|塊註釋|行註釋
替換爲
$1

優化爲:
開頭集=[^"'/]
(雙引號|單引號|開頭集+)|塊註釋|行註釋

優化爲:
(開頭集+|雙引號|單引號)|塊註釋|行註釋

優化爲:
(開頭集+|雙引號 開頭集*|單引號 開頭集*)|塊註釋|行註釋
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章