1. 程式人生 > >正則表示式的執行原理詳解(NFA引擎)

正則表示式的執行原理詳解(NFA引擎)

正則表示式 NFA 引擎是大多主流語言使用的引擎,它以表示式為主導,更符合開發的邏輯。 理解 NFA 引擎的執行規則,是十分重要的。 我們先看一個例子: 比如下邊的這行字串

The dragging belly indicates your cat is too fat

使用這個正則來匹配的結果應該是什麼呢:

fat|cat|belly|your

我們知道“或”字元表示多選分支,而且是從左到右進行匹配。那麼最終結果是 fat 嗎? 我們在 notepad++ 中進行一下匹配嘗試:

測試結果

我們發現測試的結果,是 belly ,為什麼不是最左邊的 fat 呢。下面說一下正則表示式的匹配原理: 如圖所示的例子,表示了正則表示式匹配的整個過程:

正則表示式執行規則

比如我們的字串是

hellothere,happyhippo

正則表示式為

h(ello|appy)hippo

首先說一下回溯的概念:一個最簡單的比方就是,我們打遊戲的時候,都會有個存檔點,或者叫檢查點,在這裡遊戲會進行存檔,如果在之後某時刻任務失敗或者角色死亡了,我們可以從這個存檔點重新開始嘗試。正則中的回溯,也是這個原理。 我們開始看匹配的整個過程。 1. 開始匹配時,首先從字串的第一個字元開始匹配,也就是 h ,正則中第一位也是 h ,繼續; 2. 正則中多選分支 ello 和 appy 從左邊的 ello 開始匹配,(會保留 appy 的狀態,待失敗返回檢查點進行回溯)發現可以匹配上,繼續向後匹配,正則的下一位是 h,而字串下一位是 t ,匹配失敗;此時進行回溯到 appy 的分支進行嘗試,當然 appy 是沒有辦法匹配 ello 的,在 h 的下一位嘗試就直接失敗了; 3. 然後分支都走完了,沒有成功的匹配。這時候,會在待匹配字串中,後移一位,進行嘗試,也就是從 e 處,繼續剛剛的匹配過程。當然,我們發現,e 是沒辦法匹配正則的第一位 h 的。以此過程繼續往復,l l o t h e r e , 一直到這個逗號處,都是無法匹配正則的; 4. 逗號失敗之後,我們看到剩餘的字串是 happyhippo, 也就是下一位是 h ,可以匹配正則中的第一位 h ,然後嘗試 ello 分支,顯然失敗要回溯到 appy,這裡是可以匹配的,繼續匹配 hippo,發現也是滿足的。匹配成功,正則表示式匹配到了 happyhippo 子串,匹配結束。

這個過程我們明白了之後,我們再看開始的例子。我們要知道正則表示式匹配是一個一個字元作為開始進行嘗試的。如果匹配失敗,就往後一個字元重新整個嘗試流程。 所以在 The dragging belly 這裡,前邊每個字元作為開始,都會嘗試所有的 fat|cat|belly|your 分支,當然直到 belly 前邊的空格都是匹配失敗的。直到遇到 belly 的字元 b 開始時,嘗試到 belly 分支,發現匹配成功。匹配結束。 NFA引擎,匹配的結果總是最靠左的第一個子串。