php正則失靈-最大回溯(pcre.backtrack_limit)/遞迴限制

來源:互聯網
上載者:User
php正則失效-最大回溯(pcre.backtrack_limit)/遞迴限制

昨天,同事在處理一個正則採集程式,發現了一個怪現象:在本地正則規則隨便寫都可以匹配到,可是上傳到伺服器後發現正則怎麼寫都匹配不到。自己調整了半天沒有效果,放棄?那就…………,不甘心……,吃過晚飯後,開啟電腦隨便亂狂部落格,還是google了一下,有關正則的規則,找來找去都在談怎麼寫Regex等。最後靜下心來分析了一下。

我和同事的電腦裝的都是wamp,php版本都是5.3.x,伺服器php版本是5.2.x,難道是這個問題,抱著懷疑的心情,開啟了手冊文本處理-pcre函數-preg_match_all,好傢夥原來它上面有一個函數preg_last_error,開啟看了看,那就用他試下My Code,結果返回錯誤是 PREG_BACKTRACK_LIMIT_ERROR ,原來是這個環境變數問題,於是在我代碼的開頭加入ini_set("pcre.backtrack_limit",1000000);結果正常抓取。回頭再看了下手冊,發現下面的介紹:


最後又上網查了一些資料,其中有一個博主寫的挺細的:下面轉一些相關內容,解釋一下:

在PHP的pcre擴充中, 提供了倆個設定項.


1 pcre.backtrack_limit //最大回溯數
2 pcre.recursion_limit //最大嵌套數


預設的backtarck_limit是100000(10萬).
現在要弄清這個問題的原因, 關鍵就是什麼是”回溯”.
這個正則, 使用非貪婪模式, 非貪婪模式比對原理簡單來說是, 在可配也可不配的情況下, 優先不匹配. 記錄備選狀態, 並將匹配控制交給Regex的下一個匹配字元, 當之後的匹配失敗的時候, 再溯, 進行匹配.


舉個例子:
源字串: aaab正則: .*?
匹配過程開始的時候, “.*?”首先取得匹配控制權, 因為是非貪婪模式, 所以優先不匹配, 將匹配控制交給下一個匹配字元”b”, “b”在源字串位置1匹配失敗(“a”), 於是回溯, 將匹配控制交回給”.*?”, 這個時候, “.*?”匹配一個字元”a”, 並再次將控制權交給”b”, 如此反覆, 最終得到匹配結果, 這個過程中一共發生了3次回溯.


最後,還是要說一下

1、在PHP 5.2以後, 提供了:int preg_last_error ( void )Returns the error code of the last PCRE regex execution.
我們應該經常檢查這個函數的返回值, 當不為零的時候說明上一個正則函數出錯, 特別的對於文章的例子, 出錯返回(PREG_BACKTRACK_LIMIT_ERROR)
2、非貪婪模式導致太多回溯, 必然會有一些效能問題, 適當的該寫下正則, 是可以避免這個問題的. 尤其在做大資料量的文本處理的時候, 如果正則設計不慎, 很容易導致深度嵌套, 另外考慮到效能, 還是建議能用字串處理盡量使用字串處理代替.


  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.