日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

从头开始,搭建一个正则表达式引擎(一)整体构架、预处理

發(fā)布時(shí)間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从头开始,搭建一个正则表达式引擎(一)整体构架、预处理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

大概和我不以程序員為職業(yè)有關(guān)吧,我本人是比較喜歡算法的那種,當(dāng)然是比不了科班出身的。

比如我就寫(xiě)過(guò)很多版本的算術(shù)表達(dá)式解析器,優(yōu)先級(jí)堆棧的;二叉樹(shù)的;分治策略的;修正計(jì)算順序的……

正則表達(dá)式兩個(gè)我也寫(xiě)過(guò)兩個(gè),一個(gè)采用的回溯算法,另一個(gè)則是二叉樹(shù)版本的,雖然這倆倒是都能用吧,但是對(duì)分組的處理(分組是采用遞歸調(diào)用的方法實(shí)現(xiàn)的,相當(dāng)于另一個(gè)正則表達(dá)式)實(shí)在是不太好,這個(gè)缺點(diǎn)導(dǎo)致很多時(shí)候搜索的結(jié)果會(huì)遺漏很多,而二叉樹(shù)版本的還有個(gè)缺點(diǎn)是選擇操作“|”只能獲得第一個(gè)匹配…………

就效果看,這倆都是殘次品。

后來(lái),我在vczh的博客里看到了他的一個(gè)科普貼子,在那里面,我才了解到還有有限自動(dòng)機(jī)這種方法。

之后我花了不少時(shí)間去思考,因?yàn)榭傆X(jué)得這個(gè)方法太麻煩了,斷斷續(xù)續(xù)有2-3個(gè)月吧,想來(lái)想去也沒(méi)想出什么更好的法子,最后還是覺(jué)得只有用有限自動(dòng)機(jī)才合適。

不過(guò)多少我還是做了些修改的,倒不是為了效率,是為了減少打字量……

主要修改如下:

(1)不每個(gè)字符轉(zhuǎn)移一次狀態(tài),而是盡可能的把連續(xù)的字符作為一個(gè)整體進(jìn)行比對(duì)。

(2)不弄什么字母分組表,數(shù)據(jù)結(jié)構(gòu)就使用指針鏈表,節(jié)省工作量

(3)“{a,b}”這種有次數(shù)限定的重復(fù),vczh是采用復(fù)制節(jié)點(diǎn)實(shí)現(xiàn)的,我采用增加狀態(tài)邊來(lái)解決(效率會(huì)下降)

(4)分組命名,向前向后預(yù)查這些花哨而實(shí)用的功能,俺就丟了

那么,整體上看,正則表達(dá)式引擎的設(shè)計(jì)我就劃分為如下幾個(gè)步驟:

1)對(duì)規(guī)則字符串做預(yù)處理,主要是換行這類(lèi)要使用轉(zhuǎn)義符的字符,這個(gè)預(yù)處理可以把這些字符還原

2)將規(guī)則字符串進(jìn)行劃分,修正成操作符、操作數(shù)的列表形式

3)對(duì)這個(gè)列表進(jìn)行處理,獲得NFA狀態(tài)轉(zhuǎn)移圖

4)將NFA狀態(tài)轉(zhuǎn)移圖里的ε邊消去,減少狀態(tài)轉(zhuǎn)移數(shù)

5)利用得到的狀態(tài)轉(zhuǎn)移圖,對(duì)字符串進(jìn)行匹配

第一步很容易解決,無(wú)非就是找到'\',然后將后跟't'、'n'、'r'等字符的修正為相應(yīng)的制表、換行……

第二步也相對(duì)簡(jiǎn)單,無(wú)非是識(shí)別幾個(gè)操作符:

'*'、'+'、'?'、'*?'、'+?'、'??'、'('、'(:'、')'、'|'、'['、']'、'{'、'}'

比較特殊的是:

因?yàn)榘堰B續(xù)的字符看做一個(gè)整體,所以在后跟重復(fù)或者可選運(yùn)算符時(shí),要檢查一下是否需要斷開(kāi)字符串;

'['后面要一直讀取到前面不是'\'的']',期間不作分析,結(jié)果作為一個(gè)整體

'{'后面有'{a}'、'{a,}'、'{,a}'、'{a,b}'這幾種形式,同樣是讀取為一個(gè)整體

還有一個(gè)隱藏的操作符,它的作用是將兩個(gè)操作數(shù)連接起來(lái),類(lèi)似算術(shù)里的“*”,關(guān)于它另有介紹[*]

如此一來(lái),列表里的成員記錄的內(nèi)容就會(huì)有好幾種,python里這不算啥,C++里就麻煩一些,我采用的是struct和union來(lái)回嵌套+標(biāo)志字節(jié)的辦法來(lái)處理這個(gè)問(wèn)題。

(如果使用正則表達(dá)式這一步非常輕松,可是如果用了就真成了笑話(huà)了)

第三步見(jiàn)下一帖

[*]被隱藏了的“連接”運(yùn)算符,比如“ab[cd]”這個(gè)字符串,分析后的兩個(gè)元素“ab”和“[cd]”正是通過(guò)這個(gè)操作符連接的。這個(gè)隱藏運(yùn)算符我是用后面的Operator類(lèi)的一個(gè)補(bǔ)足函數(shù)來(lái)填充修復(fù)的,不然就得另外寫(xiě)一個(gè)函數(shù)了。


轉(zhuǎn)載于:https://my.oschina.net/liudiwu/blog/111327

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的从头开始,搭建一个正则表达式引擎(一)整体构架、预处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。