<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一篇值得收藏的正則表達(dá)式文章

          共 5160字,需瀏覽 11分鐘

           ·

          2022-02-22 12:34

          點擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時間送達(dá)

          關(guān)于正則表達(dá)式,我一直使用得比較淺,一直也想好好學(xué)習(xí)下。今天分享的文章,比較細(xì)致地梳理正則表達(dá)式的各方面知識,甚至還有思維導(dǎo)圖和動圖,分享給大家一起學(xué)習(xí)

          劇照 | 《想見你》
          來源:豬哥@裸睡的豬
          目前越來越多的網(wǎng)站、編輯器、編程語言都已支持一種叫“正則表達(dá)式”的字符串查找“公式”,有過編程經(jīng)驗的同學(xué)都應(yīng)該了解正則表達(dá)式(Regular Expression 簡寫regex)是什么東西,它是一種字符串匹配的模式(pattern),更像是一種邏輯公式。

          使用正則表達(dá)式去匹配字符串Hello World 中的 Hello
          偽代碼:/Hello/, "Hello World"
          輸出:Hello

          如何寫好一篇關(guān)于 正則表達(dá)式 的文章,我思考了一周的時間,從未有一篇文章能讓豬哥如此費神。

          因為我覺得正則表達(dá)式 :難記憶、難描述、廣而深且不受重視,有人說正則表達(dá)式既好寫也難寫!

          1. 好寫:無非寫一些常用、實用的案例,說實話你們每個人都能寫出這種:在網(wǎng)上百度一下然后結(jié)合一點自己的實際經(jīng)驗,一篇文章就出來了。
          2. 難寫:很多人都認(rèn)為正則簡單,不用記,要用就百度一下。但是絕大多數(shù)人了解的只是正則的一個小面,真正的精髓卻很少關(guān)注!

          豬哥希望大家能知道正則的知識點其實非常非常多,尤其是正則引擎執(zhí)行原理以及正則優(yōu)化,這算是正則表達(dá)式的進階知識點,面試中也可能會被問到。


          一、起源與發(fā)展


          我們在學(xué)習(xí)一門技術(shù)的時候有必要了解其起源與發(fā)展過程,這對我們?nèi)ダ斫饧夹g(shù)本身有一定的幫助!
          20世紀(jì)40年代:正則表達(dá)式最初的想法來自兩位神經(jīng)學(xué)家:沃爾特·皮茨與麥卡洛克,他們研究出了一種用數(shù)學(xué)方式來描述神經(jīng)網(wǎng)絡(luò)的模型。
          1956年:一位名叫Stephen Kleene的數(shù)學(xué)科學(xué)家發(fā)表了一篇題目是《神經(jīng)網(wǎng)事件的表示法》的論文,利用稱之為正則集合的數(shù)學(xué)符號來描述此模型,引入了正則表達(dá)式的概念。正則表達(dá)式被作為用來描述其稱之為“正則集的代數(shù)”的一種表達(dá)式,因而采用了“正則表達(dá)式”這個術(shù)語。
          1968年:C語言之父、UNIX之父肯·湯普森把這個“正則表達(dá)式”的理論成果用于做一些搜索算法的研究,他描述了一種正則表達(dá)式的編譯器,于是出現(xiàn)了應(yīng)該算是最早的正則表達(dá)式的編譯器qed(這也就成為后來的grep編輯器)。
          Unix使用正則之后,正則表達(dá)式不斷的發(fā)展壯大,然后大規(guī)模應(yīng)用于各種領(lǐng)域,根據(jù)這些領(lǐng)域各自的條件需要,又發(fā)展出了許多版本的正則表達(dá)式,出現(xiàn)了許多的分支。我們把這些分支叫做“流派”。
          1987年:Perl語言誕生了,它綜合了其他的語言,用正則表達(dá)式作為基礎(chǔ),開創(chuàng)了一個新的流派,Perl流派。之后很多編程語言如:Python、Java、Ruby、.Net、PHP等等在設(shè)計正則式支持的時候都參考Perl正則表達(dá)式
          到這里我們也就知道為什么眾多編程語言的正則表達(dá)式基本一樣,因為他們都師從Perl
          注:Perl語言是一種擅長處理文本的語言,但因晦澀語法和古怪符號不利于理解和記憶導(dǎo)致很多開發(fā)者并不喜歡。
          二、語法


          完整的正則表達(dá)式由兩種字符構(gòu)成:特殊字符(元字符)和普通字符。
          ps:元字符表示正則表達(dá)式功能的最小單位,如 * ^ $ \d 等等
          關(guān)于語法部分豬哥并不想過多的講解,給大家做一個詳細(xì)的歸納整理,供大家日后快速查找吧!
          如果想系統(tǒng)學(xué)習(xí)正則表達(dá)式的語法部分,豬哥推薦 菜鳥教程: https://www.runoob.com/regexp/regexp-tutorial.html
          三、匹配原理


          匹配原理是豬哥想要重點講解的部分,也希望同學(xué)們可以認(rèn)真了解這部分的內(nèi)容。
          很多人覺得開車沒必要了解車的構(gòu)造原理,但是我們學(xué)編程的還真的需要了解原理。
          因為了解原理,你才能調(diào)優(yōu),這往往也是初級工程師與中高級工程師之間的差別點之一!

          1.執(zhí)行過程

          正則表達(dá)式的執(zhí)行,是由正則表達(dá)引擎編譯執(zhí)行的,大致的執(zhí)行流程豬哥也畫了個流程圖給大家看看。
          這里給大家提一點就是:預(yù)編譯(pre-use compile)
          豬哥建議大家在生產(chǎn)環(huán)境中使用預(yù)編譯功能,為什么呢?
          以Python語言內(nèi)置re模塊舉例:
          1. 通過re.compile(pattern)預(yù)編譯返回Pattern對象,在后面代碼中可以直接引用。
          2. 通過re.match(pattern, text)即用編譯,雖然也會有緩存Pattern對象,但是每次使用都需要去緩存中取出,比預(yù)編譯多一步取操作。

          豬哥也通過實際測試來 驗證預(yù)編譯 確實比 即用編譯 要快!
          pattern = r'http:\/\/(?:.?\w+)+'text = 'xxx.com'

          2.引擎(重點)

          既然正則表達(dá)式由執(zhí)行引擎執(zhí)行,那我們就來講講正則表達(dá)式的引擎吧,這一塊是重點,希望大家仔細(xì)看看,弄懂了理解了才行!
          正則引擎主要可以分為基本不同的兩大類:
          1. DFA (Deterministic finite automaton) 確定型有窮自動機
          2. NFA (Non-deterministic finite automaton) 非確定型有窮自動機

          ps:當(dāng)然還有一種引擎為:POSIX NFA,這是根據(jù)NFA引擎出的規(guī)范版本,但因為使用較少所以我們這里也就不重點講解。
          這里需要和大家解釋下何為確定型有窮自動機這幾個名詞:
          1. 確定型與非確定型:假設(shè)有一個字符串(text=abc)需要匹配,在沒有編寫正則表達(dá)式的前提下,就直接可以確定字符匹配順序的就是確定型,不能確定字符匹配順序的則為非確定型。
          2. 有窮:有窮即表示有限的意思,這里表示有限次數(shù)內(nèi)能得到結(jié)果。
          3. 自動機:自動機便是自動完成,在我們設(shè)置好匹配規(guī)則后由引擎自動完成,不需要人為干預(yù)!

          根據(jù)上面的解釋我們可得知DFA引擎 和 NFA引擎 的一個很大區(qū)別就是:在沒有編寫正則表達(dá)式的前提下,是否能確定字符執(zhí)行順序!
          DFA引擎執(zhí)行原理
          為了大家能很清楚的理解DFA引擎執(zhí)行原理,豬哥制作了一個簡易的動態(tài)執(zhí)行過程圖給大家看看

          根據(jù)上面的動圖我們可以得出DFA引擎的一些特點:
          1. 文本主導(dǎo):按照文本的順序執(zhí)行,這也就能說明為什么DFA引擎是確定型(deterministic)了,穩(wěn)定!
          2. 記錄當(dāng)前有效的所有可能:我們看到當(dāng)執(zhí)行到(d|b)時,同時比較表達(dá)式中的db,所以會需要更多的內(nèi)存。
          3. 每個字符只檢查一次:這提高了執(zhí)行效率,而且速度與正則表達(dá)式無關(guān)。
          4. 不能使用反向引用等功能:因為每個字符只檢查一次,文本零寬度(位置)只記錄當(dāng)前比較值,所以不能使用反向引用、環(huán)視等一些功能!

          NFA引擎執(zhí)行原理
          豬哥同樣畫了一個簡易的NFA引擎執(zhí)行過程圖方便大家理解

          根據(jù)上面的動圖我們可以得出NFA引擎的一些特點:
          1. 文表達(dá)式主導(dǎo):按照表達(dá)式的一部分執(zhí)行,如果不匹配換其他部分繼續(xù)匹配,直到表達(dá)式匹配完成。
          2. 會記錄某個位置:我們看到當(dāng)執(zhí)行到(d|b)時,NFA引擎會記錄字符的位置(零寬度),然后選擇其中一個先匹配。
          3. 單個字符可能檢查多次:我們看到當(dāng)執(zhí)行到(d|b)時,比較d后發(fā)現(xiàn)不匹配,于是NFA引擎換表達(dá)式的另一個分支b,同時文本位置回退,重新匹配字符'b'。這也是NFA引擎是非確定型的原因,同時帶來另一個問題效率可能沒有DFA引擎高。
          4. 可實現(xiàn)反向引用等功能:因為具有回退這一步,所以可以很容易的實現(xiàn)反向引用、環(huán)視等一些功能!

          兩種引擎比較
          關(guān)于這兩種引擎的總結(jié),豬哥引用《精通正則表達(dá)式》書本中的一句話來概括:
          DFA(電動機) 和NFA(汽油機) 都有很長的歷史,不過,正如汽油機一樣,NFA 的歷史更長一些。也有些系統(tǒng)采用了混合引擎,它們會根據(jù)任務(wù)的不同選擇合適的引擎(甚至對同一表達(dá)式中的不同部分采用不同的引擎,以求得功能與速度之間的最佳平衡)。? ? ? ?——《精通正則表達(dá)式》

          3.回溯(重點)

          作為絕大多數(shù)編程語言都選擇的引擎——NFA (非確定型有窮自動機) 引擎,我們當(dāng)然要再詳細(xì)了解一下它的精髓——回溯

          動圖中,我們可以看到當(dāng)某個正則分支匹配不成功之后,文本的位置需要回退,然后換另一個分支匹配,而回退這步專業(yè)術(shù)語就叫:回溯
          回溯的原理類似我們走迷宮時走過的路設(shè)置一個標(biāo)志物,如果不對則原路返回,換另一條路。
          回溯機制不但需要重新計算正則表達(dá)式文本的對應(yīng)位置,也需要維護括號內(nèi)的子表達(dá)式所匹配文本的狀態(tài)(b匹配成功),保存到內(nèi)存中以數(shù)字編號的組中,這就叫捕獲組
          保存括號內(nèi)的匹配結(jié)果之后,我們在后面的正則表達(dá)式中就可以使用,這就是我們所說的反向引用,在上面的案例中只有一個捕獲,所以$1=b
          回溯陷阱:講到回溯必須提到回溯陷阱,它導(dǎo)致的結(jié)果就是機器CPU使用率爆滿(超100%),機器就卡死了。
          舉個例子:text=aaaaa,pattern=/^(a*)b$/,匹配過程大致是
          1. (a*):匹配到了文本中的aaaaa
          2. 匹配正則中的b,但是失敗,因為(a*)已經(jīng)把text都吃了
          3. 這時候引擎會要求(a*)吐出最后一個字符(a),但是無法匹配b
          4. 第二次是吐出倒數(shù)第二個字符(還是a),依然無法匹配
          5. 就這樣引擎會要求(a*)逐個將吃進去的字符都吐出來
          6. 但是到最后都無法匹配b

          這里的重點就在于 引擎會要求*匹配的東西一點一點吐回,我們假設(shè)如果文本長度為幾萬,那引擎就要回溯幾萬次,這對機器的CPU來說簡直是災(zāi)難。
          有些復(fù)雜的正則表達(dá)式可能有多個部分都要回溯,那回溯次數(shù)就是指數(shù)型。如果文本長度為500,一個表達(dá)式有兩部分都要回溯,那次數(shù)可能是500^2=25萬次,這誰受得了!
          關(guān)于更多更詳細(xì)的回溯介紹,推薦大家可以閱讀《精通正則表達(dá)式》這本書!
          四、優(yōu)化


          編寫巧妙的正則表達(dá)式不僅僅是一種技能,而且還是一種藝術(shù)。
          上面我們了解到,絕大多數(shù)的編程語言都采用的是NFA引擎,而NFA引擎的特點是:功能強大、但有回溯機制所以效率慢。所以我們需要學(xué)習(xí)一些NFA引擎的一些優(yōu)化技巧,以減少引擎回溯次數(shù)以及更直接的匹配到結(jié)果!
          針對NFA引擎的可優(yōu)化的點其實挺多的,為了方便大家記憶,豬哥也畫幅結(jié)構(gòu)圖歸納一下,方便大家收藏細(xì)看。

          在面試過程中也許會被問到關(guān)于正則的優(yōu)化,大家記住幾點就可以。
          五、推薦


          上面我們講解了關(guān)于正則表達(dá)式的誕生和發(fā)展、引擎、優(yōu)化等知識,但是關(guān)于正則表達(dá)式的知識點遠(yuǎn)遠(yuǎn)不止這些,所以最后豬哥推薦一些好的學(xué)習(xí)資料,大家有空可以了解學(xué)習(xí)下。

          1.書

          推薦正則表達(dá)式的書,那必然是《精通正則表達(dá)式》 ,目前這本書已經(jīng)出了第三版,豆瓣評分8.9。
          內(nèi)容雖然稍有啰嗦,但是對于正則新手很友好,唯一不足是Python案例少。

          2.博客

          入門:菜鳥教程:https://www.runoob.com/regexp/regexp-tutorial.html
          深入:某不知名大佬:https://blog.csdn.net/lxcnn

          3.在線測試工具

          https://regex101.com/,這個網(wǎng)站可以選擇不同編程語言的正則支持,有語義分析、匹配測試、參考列表等,非常實用。

          4.常用案例

          一些簡單常用的小案例匯總,菜鳥教程:http://c.runoob.com/front-end/854

          最后祝愿大家都能搞定正則表達(dá)式,處理文本可以得心應(yīng)手!

          下載1:OpenCV-Contrib擴展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實戰(zhàn)項目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實戰(zhàn)項目即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學(xué)校計算機視覺。

          下載3:OpenCV實戰(zhàn)項目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實戰(zhàn)項目20講即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學(xué)習(xí)進階。


          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99这里只有精品国产 | 日韩无码成人一区黄色电影 | 天天干天天日天天草 | 亚洲无码日韩高清AV | 青青草,新红楼丁香在线 |