首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP preg_match 正則匹配長字串失敗?調整 pcre.backtrack_limit 解決

     編輯:PHP 綜合知識

問題現象

使用 preg_match 或 preg_match_all 處理超長字串 (如完整 HTML 頁面、大型 JSON) 時,函式回傳 false 且無錯誤訊息,實際上是觸發了 PCRE 回溯限制。

根本原因

PHP 5.2.0 引入 pcre.backtrack_limit (預設 100,000) 限制正則引擎回溯次數,防止惡意正則導致 CPU 耗盡。超過限制時匹配直接失敗。

解決方案

// 在執行正則前調大限制 (視記憶體而定)
ini_set('pcre.backtrack_limit', 1000000); // 100 萬
ini_set('pcre.recursion_limit', 100000);  // 遞迴限制,防止堆疊溢位

// 建議同時限制記憶體
ini_set('memory_limit', '256M');

參數說明

參數預設值作用調整建議
pcre.backtrack_limit100000最大回溯步數長字串匹配失敗時調大,但過大導致 CPU 飆高
pcre.recursion_limit100000最大遞迴深度配合 backtrack_limit 調整,過大導致 PHP 崩潰
memory_limit128M腳本記憶體上限確保有足夠緩衝處理大字串

最佳實踐

  1. 優化正則:避免 .* 貪婪匹配,改用 .*? 或具體字元類別 [^<>]*。
  2. 分塊處理:超大文件改用流式解析 (XMLReader、JSON 流式解析器) 而非一次性載入匹配。
  3. 臨時調大:僅在該函式前後 ini_set,避免影響全域。

驗證是否觸發限制

$result = @preg_match($pattern, $longString);
if ($result === false) {
    $error = preg_last_error();
    if ($error === PREG_BACKTRACK_LIMIT_ERROR) {
        error_log('PCRE backtrack limit exceeded');
    } elseif ($error === PREG_RECURSION_LIMIT_ERROR) {
        error_log('PCRE recursion limit exceeded');
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved