日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁編程開發(fā)其它知識 → 高性能的正則表達(dá)式效率優(yōu)化

      高性能的正則表達(dá)式效率優(yōu)化

      相關(guān)軟件相關(guān)文章發(fā)表評論 來源:smildlzj時間:2011/12/9 0:59:50字體大。A-A+

      作者:smildlzj點(diǎn)擊:612次評論:0次標(biāo)簽: 正則 正則表達(dá)式

      • 類型:電子教程大。9.5M語言:中文 評分:8.0
      • 標(biāo)簽:
      立即下載

      前言

      編寫高性能的正則表達(dá)式,有如下幾條規(guī)則,這幾條規(guī)則是本人總結(jié)出來的:

      1、使用正確的邊界匹配器(^、$、\b、\B等)

      2、使用具體的元字符、字符類(\d、\w、\s等) 

      3、使用正確的量詞(+、*、?、{n,m})

      4、使用非捕獲組、原子組

      5、注意量詞的嵌套 

      其實(shí)正則表達(dá)式的很多優(yōu)化技巧都是圍繞著“減少回溯”這樣一個原則進(jìn)行優(yōu)化的。

      至于什么是“回溯”,筆者就不在這里重復(fù)了,以下通過具體的例子理解這樣的過程。

      示例

      一、以下是一則匹配電子郵件地址的正則表達(dá)式:

      ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$ 

       先一步步的解析:

      1、^\w+:表示必須以字符開始, 且是一個或者多個;

      2、([\.-]?\w+)*中的“[\.-]?”表示匹配“.”或者“-”,零次或者一次;

      3、([\.-]?\w+)*中的“\w+”則表示匹配一個或者多個的字符;

      4、([\.-]?\w+)*整個則表示匹配.xxx、-xxx或者xxx這樣的字符,且零次或者多次;

      5、第1-4步,則匹配sunny或者sunny.yang這樣的字符;

      6、“@”則是具體元,匹配具體的@; 

      7、 \w+:則表示匹配的一個或者多個的字符,因?yàn)閑mail不可能這樣嘛:sunny@.gmail.com;

      8、 ([\.-]?\w+)*:則跟第2-4步一樣,匹配.163、-lib、.gd這樣的字符,且零次或者多次;

      9、 (\.\w{2,3})+$:則匹配.com、.cc這樣結(jié)尾的域名,且因?yàn)閈w{2,3}限定了長度必須為2-3位,所以不能匹配.c、.n這樣的字符。

      乍看這樣一個解析過程沒問題,邏輯正確,但其實(shí)暗藏很多問題,看看以下的一個匹配圖,backtrack則表示回溯(使用RegexBuddy可以很清晰的看到這過程)


       整個成功的匹配過程經(jīng)歷了55步,我們先分析下整個匹配過程:

      1、圖中的第1和2步,匹配^\w+,匹配成功,匹配了“admin”;

      2、圖中第3步,匹配[\.-]?,當(dāng)然由于不存在“.”和“-”,因此沒匹配上具體的字符,但又由于“?”的限定,可以匹配零或者一次,因此這個子表達(dá)式匹配成功,雖然沒匹配上具體的字符。

      3、圖中第4步,匹配\w+,由于“+”限定一個或者多個以上字符,但后續(xù)已經(jīng)沒[a-zA-Z0-9]可以匹配了,因此產(chǎn)生回溯,回溯到上次匹配成功的位置,也就admin; 

      4、圖中第5步,因?yàn)樯弦徊疆a(chǎn)生了回溯,所以“[\.-]?\w+”匹配了零次,由于([\.-]?\w+)*中限定零次或者多次,因此也匹配成功,也沒匹配上具體的字符; 

      以下步驟,匹配該過程: 

      ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$

      5、圖中第6步,匹配了“@” ,第7步匹配了“\w+”,即匹配了“open”;

      6、圖中第8-13步,匹配“([\.-]?\w+)*” ,匹配了“-lib”、“.com”,匹配“.com”可能與我們期望不相符,我們期望這子表達(dá)式匹配的是www.xx.gd.cn中的“.gd”;

      7、圖中第7-10步,匹配了open-lib,第7-13步則匹配了open-lib.com;

      8、因?yàn)椤?[\.-]?\w+)*”中的量詞是“*”,則繼續(xù)重復(fù)這個過程;

      9、 圖中第14步,匹配“([\.-]?\w+)*”中的“[\.-]?”,因?yàn)榇藭r指針已經(jīng)位于@open-lib.com之后了,但由于量詞“?”,因此也匹配成功,但沒匹配上字符,也沒字符可匹配;

      10、 圖中第15步,匹配“([\.-]?\w+)*”中的“\w+”,此時指針仍位于字符串末尾,沒任何字符能匹配,所以匹配失敗,產(chǎn)生回溯,回到上次成功的位置,即圖中的第13步,繼續(xù)下個表達(dá)式的匹配;

      11、 圖中第16步,匹配(\.\w{2,3})+中的“\.”,由于沒有任何字符能匹配,匹配失敗,進(jìn)行回溯;

      12、圖中第17步 ,(\.\w{2,3})+中量詞“+”,表示該表達(dá)式必須匹配一次或者多次,由于上一步匹配失敗了,所以匹配零次,但不符合一次或者多次的限定,因此繼續(xù)回溯;

      13、由于上一步匹配失敗,需要進(jìn)行回溯,因此表達(dá)式?jīng)]有更多的分支了,只能將指針回退一個字符,回溯上次成功的位置,即([\.-]?\w+)*中\(zhòng)w+的位置(這是上次產(chǎn)生分支的位置);

      14、圖中剩下的步驟,就重復(fù)著匹配([\.-]?\w+)*,回退字符,匹配(\.\w{2,3})+這樣的過程,直到匹配成功。 


      二、以下看看另外一則同樣匹配郵件地址的正則表達(dá)式:

      ^\w+([-\.]\w+)*@\w+([-\.]\w+)*\.\w+([-\.]\w+)*$

       這個正則跟上面的看起來貌似差不多,不過細(xì)看還是有區(qū)別的,也先一步步來解析:

      1、^\w+:表示必須以字符開始, 且是一個或者多個(這一步與上面的一樣); 

      2、 ([-\.]\w+)*中的“[-\.]”表示匹配“-”或者“.”;

      3、 ([-\.]\w+)*中的“\w+”則表示匹配一個或者多個的字符;

      4、([-\.]\w+)*整個則表示匹配.xxx、-xxx這樣的字符,且零次或者多次;

      5、第1-4步,則匹配sunny或者sunny.yang這樣的字符; 

      6、“@”則是具體元,匹配具體的“@”; 

      7、 \w+:則表示匹配的一個或者多個的字符,因?yàn)閑mail不可能這樣嘛:sunny@.gmail.com; 

      8、([-\.]\w+)*:則跟第2-4步一樣,匹配.163、-lib、.gd這樣的字符,且零次或者多次; 

      9、“\.”則是具體元,匹配“.”;

      10、\w+:則匹配一個或者多個字符;

      11、([-\.]\w+)*:則匹配“.com”、“-lib”、“.c”這樣的字符,且可以零次或者多次;

      12、$ :則表示結(jié)尾

      乍看這個正則的步驟過程貌似比上一則長,其實(shí)不然,同時這個正則也存在著問題,先看看匹配圖,同樣backtrack表示回溯:


      對的,你沒看錯,整個正確的匹配過程用了19步,對比前面的55步,簡直天與地的差別。,我們繼續(xù)分析下匹配過程:

      1、圖中的第1和2步,匹配^\w+,匹配成功,匹配了“admin”;

      2、圖中第3步,匹配[-\.],當(dāng)然由于不存在“.”和“-”,因此沒匹配上具體的字符,也沒具體的量詞允許匹配零次,所以不用繼續(xù)往下匹配了,因此直接產(chǎn)生了回溯; 

      3、圖中第4步,因?yàn)樯弦徊疆a(chǎn)生了回溯,所以“[-\.]\w+”匹配了零次,由于([-\.]\w+)*中限定零次或者多次,因此也匹配成功,也沒匹配上具體的字符;

       以下步驟,匹配該過程: 

      ^\w+([-\.]\w+)*@\w+([-\.]\w+)*\.\w+([-\.]\w+)*$

      4、圖中第6步\w+,匹配了open;

      5、圖中第7-12步匹配([-\.]\w+)*,匹配了“-lib”和“.com”;

      6、因?yàn)椤?[-\.]\w+)*”中的量詞是“*”,則繼續(xù)重復(fù)這個過程;

      7、圖第13步,匹配([-\.]\w+)* ,因?yàn)榇藭r指針已經(jīng)位于@open-lib.com之后了,也沒具體的量詞允許匹配零次,因此匹配失敗,回溯到上次成功的位置;

      8、圖第14步,匹配 ([-\.]\w+)*$中的“[-\.]”,此時指針仍位于字符串末尾,沒任何字符能匹配,所以匹配失敗,產(chǎn)生回溯,回到上次成功且還沒嘗試過的位置,即圖中的第9步;

      9、經(jīng)過上面的回溯,指針已經(jīng)位于@open-lib之后的位置了;

      10、圖第15步匹配了“.”,第16步\w+則匹配了“com” ;

      11、圖第17步匹配([-\.]\w+)*,由于此時指針又位于字符串末尾,因此[-\.]部分沒匹配上任何字符,因此產(chǎn)生回溯;

      12、圖第18步,由于 ([-\.]\w+)*的量詞是“*”,表示匹配零次或多次,雖然子表達(dá)式[-\.]匹配失敗,所以整個表達(dá)式匹配了零次,也是匹配成功;

      13、最后一步第19步,“$”表示末尾匹配,因?yàn)榇藭r指針位于字符串末尾,故符合,因此也匹配成功。

      分析

      整個匹配過程關(guān)鍵優(yōu)化地方,還是回溯,兩個示例表達(dá)式看起來相近,匹配過程也部分類似,但兩個例子的效率卻如此大的分別,現(xiàn)在來分析一下造成回溯的原因。

      對比下兩個表達(dá)式不同的部分:

      ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$ 

      ^\w+([\.-]\w+)*@\w+([\.-]\w+)*\.\w+([-\.]\w+)*$

        相關(guān)評論

        閱讀本文后您有什么感想? 已有人給出評價!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評論

        最新評論

        發(fā)表評論 查看所有評論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)