注意:關於正則表達式的規則,網上內容已經很多了。所以本文不講述正則表達式的規則,只講其背后的算法原理。
1. 引入
正則表達式,Regular Expression,使用單個字符串來描述、匹配一系列滿足某種句法規則的字符串。
在很多文本編輯器里,正則表達式通常被用來檢索、替換那些匹配某個模式的文本。
最常見的,比如“.”,其中“.”表示匹配除“\n”之外的任何單個字符,“”表示匹配前面的子表達式零次或多次。
在python中,正則表達式的使用也很簡單:
import re
regexObject = re.compile(r".*abc.*", flags=0) # 匹配含有abc的字符串
s1 = 'asd abc sd abc'
s2 = 'sdfsabcsdffa'
s3 = 'fsadf'
match1 = re.search(regexObject, s1) # <_sre.SRE_Match at 0x66473d8>
match2 = re.search(regexObject, s2) # <_sre.SRE_Match at 0x6647b90>
match3 = re.search(regexObject, s3) # None
但是,正則表達式的內部原理是怎么樣的呢? 它是按照什么算法來進行字符串匹配? 這就是本文要解釋的內容。
2. 狀態機
2.1 有限狀態系統
下面直接給出幾個有限狀態系統的實例,從直觀上就能理解有限狀態系統:
- 例1:指針式鍾表,一共有12*60*60個狀態,每過一秒,鍾表就從一種狀態轉換到另一種狀態
- 例2:圍棋共有3**361個狀態,每走一步棋,就從一個狀態轉換到另一個狀態
- 例3:語言的識別
2.2 有限狀態機
有限狀態機(英語:finite-state machine,縮寫:FSM)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。
有些地方也叫“自動機”,指的都是同一個東西。
FSM的表示,我們常用狀態轉移圖
。下圖就是一個模式字符串的FSM狀態轉移圖
:
給定待匹配的字符串”abababaca”,就能通過模式串的FSM進行匹配,這就是正則表達式的匹配思想。
3. 正則表達式匹配實例
給定正則表達式a(bb)+a
,其中+
表示匹配前面的子表達式一次或多次,所以字符串abba
或abbbba
都能被這個模式所匹配。
下圖是該正則表達式對應的FSM狀態轉移圖
。
該FSM中,圈代表不同的狀態。讀入字符串時,就從一個狀態進入另一個狀態。FSM有開始和匹配(匹配)兩種特殊狀態,分別位於頭部和尾部。
下面是匹配的過程示例圖:
該狀態機結束於最后一個狀態,這是一個匹配成功的狀態。若狀態機結束於非匹配成功狀態,那么匹配失敗。如果在運行過程中,沒有辦法到達其他狀態,那么狀態機提前結束。
4. 多路徑匹配
正則表達式等效於有限狀態機,每一個正則表達式都有一個對應的有限狀態機。反之,有限狀態機也對應一個正則表達式。具體的對應關系可以參見這篇文章(https://sine-x.com/regexp-1/)。
下面是多路徑的算法匹配過程:
匹配時,可能有多條路徑,遇到分支時,可以采用試錯法,一條走不通,再嘗試另一條。但這種做法效率較低。
所以另一種更優的做法,是在分支處同時匹配多條分支,同時保持多個狀態,這樣避免了很多不必要的嘗試。
參考
本文中的圖是直接從下文中截取出來再編輯的,在此感謝原圖作者!