preg_replace() 核心語法
preg_replace(
string|array $pattern,
string|array $replacement,
string|array $subject,
int $limit = -1,
int &$count = null
): string|array
常用替換模式速查
| 需求 | 模式 | 替換 | 說明 |
刪除 <style> 標籤及內容 |
/<style>.+?<\/style>/is |
'' |
s 讓 . 匹配換行,i 忽略大小寫,? 非貪婪 |
| 刪除所有 HTML 標籤 |
/<[^>]+>/ |
'' |
匹配 < 到 > 之間任意非 > 字符 |
| 刪除多餘空白 |
/\s+/ |
' ' |
合併連續空白為單空格 |
| 提取標籤屬性 |
/<img\s+[^>]*src=["']([^"']+)["']/i |
'$1' |
捕獲組提取 src 值 |
| 駝峰轉下劃線 |
/([a-z])([A-Z])/ |
'$1_$2' |
再 strtolower() |
模式修飾符詳解
| 修飾符 | 常量 | 作用 |
i | PCRE_CASELESS | 忽略大小寫匹配 |
s | PCRE_DOTALL | . 匹配換行符(默認不匹配) |
m | PCRE_MULTILINE | ^ $ 匹配每行首尾(非整個字符串) |
x | PCRE_EXTENDED | 忽略模式中的空白、允許註釋 #,提升可讀性 |
u | PCRE_UTF8 | **關鍵**:按 UTF-8 字符處理,支援中文、Emoji,防止字節級錯誤匹配 |
U | PCRE_UNGREEDY | 反轉貪婪模式,* + 變非貪婪,*? 變貪婪 |
修飾符組合示例
<?php
// 處理中文 HTML,跨行匹配
$clean = preg_replace('/<script>.+?<\/script>/isu', '', $html);
// 可讀性模式:提取郵箱
$pattern = '/
[\w.+-]+ # 用戶名部分
@
[\w-]+ # 域名
(?:\.[\w-]+)+ # 後綴
/ux';
preg_match_all($pattern, $text, $matches);
ereg/eregi 遷移指南(PHP 7.0 移除)
| 舊函數 | 新替代 | 關鍵差異 |
ereg($pattern, $str, &$regs) |
preg_match('/' . $pattern . '/', $str, $matches) |
preg 返回 bool,匹配結果在 $matches[0] (完整)、$matches[1] (第一捕獲組)... |
eregi($pattern, $str, &$regs) |
preg_match('/' . $pattern . '/i', $str, $matches) |
用 i 修飾符替代不區分大小寫 |
ereg_replace($pattern, $repl, $str) |
preg_replace('/' . $pattern . '/', $repl, $str) |
同理 |
eregi_replace(...) |
preg_replace('/' . $pattern . '/i', $repl, $str) |
同理 |
split($pattern, $str) |
preg_split('/' . $pattern . '/', $str) |
或 explode() 如果非正則 |
遷移實例
<?php
// 舊:檢查 body 標籤並提取屬性與內容
// eregi("<body([^>]+)>(.+)</body>", $data, $b);
// $b[0] 完整匹配,$b[1] 屬性,$b[2] 內容
// 新:
if (preg_match('/<body([^>]+)>(.+)<\/body>/is', $data, $matches)) {
$full = $matches[0];
$attrs = $matches[1];
$content = $matches[2];
}
// 舊:split 分割
// $parts = split('\s+', $str);
// 新:
$parts = preg_split('/\s+/', $str);
// 或純字符串分割(更快):
$parts = explode(' ', $str); // 單一分隔符用 explode
性能優化原則
- 能用
str_replace / strtr 就不用正則:字符串替換快 10-100 倍
- 預編譯模式: 循環外定義
$pattern = '/.../'; 避免重複編譯
- 避免災難性回溯:
(.+)*、(a+)+ 等嵌套量詞,改用佔有優先量詞 .*+、a++ 或原子組 (?>...)
- 使用
u 修飾符處理 UTF-8:防止多字節字符被拆分匹配導致錯誤/性能下降
- 限制替換次數:
preg_replace($pattern, $repl, $str, 1) 只替換第一處
PCRE2 升級(PHP 7.3+)
PHP 7.3 升級至 PCRE2,帶來:
- 更嚴格的語法檢查(如
[\w-] 中連字符需轉義或置首尾)
- 新特性:命名捕獲組
(?<name>...)、條件匹配、遞歸模式
- 更好的 Unicode 支援(屬性
\p{L}、腳本 \p{Han})
<?php
// PCRE2 新語法:提取中文段落
preg_match_all('/(?<chinese>\p{Han}+)/u', $text, $matches);
// $matches['chinese'] 直接獲取命名組結果