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

PHP preg_replace 正則替換完全指南:語法、修飾符、回調、向後引用與實戰避坑

     編輯:PHP 相關知識

正則表達式是文本處理的瑞士軍刀。PHP preg_replace() 作為 PCRE 庫的核心接口,功能強大但細節眾多。本文系統梳理語法規則、定界符、修飾符、回調替換、向後引用,並給出生產級實戰模式。

函數簽名與核心參數

preg_replace(
    mixed $pattern,      // 正則模式 (字符串或陣列)
    mixed $replacement,  // 替換內容 (字符串、陣列、可調用對象)
    mixed $subject,      // 目標字符串 (或陣列)
    int $limit = -1,     // 最大替換次數 (-1 無限制)
    int &$count = null   // 實際替換次數引用返回
): mixed

關鍵差異:JS String.replace 預設只替換首次匹配 (需 /g 全局),PHP preg_replace 預設全局替換所有匹配,$limit 控制上限。

定界符選擇與轉義策略

PCRE 要求模式被定界符包裹。常用 /、#、~、%。

$url = 'https://example.com/path/';

// 方案 A: / 定界符,需轉義內部 /
preg_replace('/http:\/\/example\.com\//', 'https://new.com/', $url);

// 方案 B: # 定界符,無需轉義 / (推薦含路徑 URL)
preg_replace('#https://example\.com/#', 'https://new.com/', $url);

// 方案 C: 變量插值雙引號 + 定界符
$pattern = "#^$prefix#"; // 雙引號解析變量

最佳實踐:模式含 / (路徑、HTML 標籤) 用 #;含 # 用 ~;通用情況堅持 / 形成肌肉記憶 (JS/Python/Go 同用 /)。

修飾符 (Pattern Modifiers) 完整表

修飾符作用備註
i忽略大小寫最常用
m多行模式:^/$ 匹配行首尾配合 \n 字符串
s. 匹配換行符 \n單行模式 (DOTALL)
x忽略模式中未轉義空白,可寫註釋複雜正則可讀性
e已棄用/移除 (PHP 7.0+) preg_replace_callback 替代安全風險極高
A強制從字符串開頭匹配等價 ^ 但更快
D$ 僅匹配字符串絕對末尾忽略末尾 \n,與 m 衝突
S分析非錨定模式優化 (研究用)罕用
U反貪婪:量詞預設非貪婪,? 恢復貪婪調試用,不推薦生產
X嚴格模式:非標準轉義報錯開發階段建議開啟
uUTF-8 模式:正確處理多字節字符中文必加,否則按字節匹配
J允許重複命名子組 (?<name>...)PHP 7.0+

中文與編碼處理

$str = 'W3CSchool 在線教程';

// 錯誤:無 u 修飾符,中文按字節拆分匹配失敗
preg_replace('/在線/', 'Online', $str); // 可能不生效

// 正確:強制 UTF-8
preg_replace('/在線/u', 'Online', $str); // W3CSchool Online教程

// 忽略大小寫 + UTF-8
preg_replace('/w3cschool/iu', 'W3C', $str);

換行符與多行模式實戰

$text = "Line1\nLine2\nLine3";

// 無 s 修飾符:. 不匹配 \n
preg_replace('/^Line.*Line$/m', '[BLOCK]', $text); 
// m: ^$ 匹配每行,但 . 不跨行,結果無替換

// 加 s:. 匹配 \n,整段視為單行
preg_replace('/^Line.*Line$/s', '[BLOCK]', $text); 
// 結果: [BLOCK]

// 多行替換每行
preg_replace('/^/m', '> ', $text); // > Line1\n> Line2\n> Line3

回調替換:preg_replace_callback (替代棄用 /e)

<?php
$html = '<a href="HTTP://EXAMPLE.COM">Link</a>';

// 將 URL 標準化為小寫
$html = preg_replace_callback(
    '#href="([^"]+)"#i',
    function ($matches) {
        return 'href="' . strtolower($matches[1]) . '"';
    },
    $html
);
// 輸出: Link

// 靜態方法回調 (PHP 5.3+)
class Sanitizer {
    public static function lowerUrl($m) { return 'href="' . strtolower($m[1]) . '"'; }
}
preg_replace_callback('#href="([^"]+)"#i', ['Sanitizer', 'lowerUrl'], $html);

向後引用:捕獲組在替換中的使用

語法說明示例
$1 $2...PHP 雙引號字符串中推薦 (單引號不解析)preg_replace('/(\d+)-(\d+)/', '$2-$1', '123-456') → 456-123
\1 \2...單引號字符串或 JS 風格preg_replace('/(\d+)-(\d+)/', '\\2-\\1', '123-456')
${1} ${name}消除歧義 (如 $11 是第 11 組還是第 1 組+字符 1)preg_replace('/(?<num>\d+)/', '${num}0', '5') → 50

巢狀捕獲組編號規則

$pattern = '/^((\w+)\s+(\d+))$/'; // 外層組1,內層組2、3
$replacement = 'Full:$1 Word:$2 Num:$3';
preg_replace($pattern, $replacement, 'Hello 123');
// Full:Hello 123 Word:Hello Num:123

實戰模式庫

場景模式替換說明
XSS 過濾 script 標籤#<script[^>]*>.*?</script>#is''s 跨行,i 忽略大小寫
提取 img src#<img[^>]+src=["']([^"']+)["']#i回調收集 $1非貪婪屬性匹配
手機號脫敏#(\d{3})\d{4}(\d{4})#'$1****$2'捕獲首尾 4 位
Markdown 鏈接轉 HTML#\[([^\]]+)\]\(([^)]+)\)#'<a href="$2">$1</a>'命名組更清晰
去除多餘空白行#\n\s*\n#"\n\n"保留單空行

性能優化鐵律

  1. 能用 str_replace/strtr 絕不用正則 (固定字符串替換快 10-100 倍)。
  2. 預編譯複用:循環中固定模式定義在循環外,避免重複編譯。
  3. 避免災難性回溯:(.*)*、(a+)+ 等嵌套量詞在長字符串導致指數級回溯,改用 (?>...) 原子組或具體字符類。
  4. 錨定優化:^、\A、$、\z 讓引擎快速失敗/成功。
  5. JIT (PHP 8+):PCRE2 JIT 自動優化熱點模式,無需代碼變更。

正則強大但雙刃劍。掌握 PHP preg_replace 完整語義、修飾符交互、回調替換、向後引用細節,配合性能鐵律,才能寫出高效、可維護、安全的文本處理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved