正規表示式匹配原理

admin發表於2018-09-07

一.正規表示式引擎:

當前正規表示式引擎主要分為兩種,這裡不做詳細介紹,可能絕大多數朋友並不關心這個。

只要關心我們當前所使用的正規表示式引擎是如何工作即可。

正規表示式引擎主要分類:

(1).DFA(Deterministic finite automaton),確定型有窮自動機。

(2).NFA(Non-deterministic finite automaton),非確定型有窮自動機。

當前大多數語言都是使用傳統型NFA正則引擎,因為它更為強大靈活,JavaScript也是如此。

本文將通過程式碼例項詳細分析一下正規表示式的匹配過程。

二.字串的組成:

要理解正規表示式匹配原理,首先要知道正則如何理解字串的構成。

圖示如下:

a:3:{s:3:\"pic\";s:43:\"portal/201809/07/124432lhvkvu9qfqi175zf.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

字串不僅由字元組成,還包括位置,"antzone"是由7個字元和8個位置構成。

三.零寬和非零寬匹配單元:

大體上,正規表示式可以匹配到兩種型別內容。

(1).位置。

(2).非位置。

如果正規表示式匹配單元匹配到的是位置或者匹配到的內容不儲存,那麼此匹配單元就是零寬的。

如果正則匹配單元匹配到的內容是正常字元,並且將匹配到的內容儲存起來,那麼此匹配單元是佔有寬度的。

特別說明:匹配單元就是正規表示式中任意一個可以匹配內容的單元。

程式碼如下:

[JavaScript] 純文字檢視 複製程式碼
let reg=/t\d/g;

上面程式碼中t和\d都是一個匹配單元,當然簡單的匹配單元也可以組合成複雜的匹配單元。

零寬匹配單元是非互斥的,也就是一個位置可以同時由多個零寬的匹配單元匹配。

佔有寬度的匹配單元是互斥的,一個匹配單元匹配到指定內容之後,這些內容不能再被其他佔有寬度正則匹配。

四.控制權的傳遞:

正規表示式當開始匹配的時候,一個正則匹配單元獲得控制權,從字串中的某一個位置開始嘗試匹配。

一個正則匹配單元開始嘗試匹配的位置,是從前一個正則匹配單元匹配成功的結束位置開始。

控制權傳遞分析如下:

[JavaScript] 純文字檢視 複製程式碼
(匹配單元一)(匹配單元二)

如果匹配單元一是零寬的,那麼匹配起始與結束位置相同,如果位置是0,那麼匹配單元二將從位置0開始匹配。如果匹配單元一是佔有寬度的,開始匹配位置0,結束匹配位置是字元"z",那麼匹配單元二開始匹配位置就是4。

五.正規表示式匹配分解:

分解演示一:

(1).將要進行匹配的字串:"antzone"。

(2).正規表示式:/zone/。

匹配過程如下:

首先由正規表示式中字元"z"取得控制權,然後去嘗試匹配字串中的第一個字元"a",匹配失敗。

則繼續嘗試第二個字元"n"依然會失敗,直到字元"z",匹配成功。

這樣控制權由正規表示式中的字元"z"傳遞給字元"o",由於字元"z"已經被匹配。

所以字元"o"將會從位置4開始匹配,由"o"來匹配"o",匹配成功。

這樣依次傳遞下去,最終正規表示式匹配成功,匹配結果為"zone"。

例項演示如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let str="antzone";
let reg=/zone/;
console.log(str.match(reg));

分解演示二:

(1).將要進行匹配的字串:"antzone"。

(2).正規表示式:/\ban?t/。

匹配過程如下:

首先正規表示式中的元字元\b取得控制權,開始嘗試匹配字串"antzone",匹配的是單詞邊界位置。

匹配成功後,控制權交給正規表示式字元"a"。

由於"\b"是零寬的,所以"a"從位置0開始匹配,匹配字元"a"成功。

然後將控制權交給"n?",由於“?”是匹配優先量詞(同時記錄一個備選狀態,如果匹配不成功則進行回溯),所以會先嚐試進行匹配,能夠成功"n",控制權然後交給字元"t",也能夠匹配成功,匹配結果為:"ant"。

例項演示如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let str="antzone";
let reg=/\ban?t/;
console.log(str.match(reg));

相關文章