正則表達式是字串處理的瑞士刀,但寫得不好既難維護又低效。本文聚焦 PHP PCRE (preg_*) 函式族,總結核心語法、常用元字符、修飾符、進階斷言、回調替換等實戰技巧,並附代碼範例。
模式需包裹在分隔符中,慣用 /pattern/modifiers:
| 修飾符 | 說明 |
|---|---|
i | 忽略大小寫 |
m | 多行模式:^$匹配每行首尾 |
s | 單行模式:.匹配含換行的任意字元 |
x | 忽略模式中的空白(可寫註解) |
u | UTF-8 模式(處理中文必備) |
U | 非貪婪模式:匹配最短字串 |
e | 替換字串視為 PHP 代碼執行(**已棄用,請用 preg_replace_callback**) |
| 元字符 | 含義 | 範例 |
|---|---|---|
\A | 字串開頭 | |
\Z | 字串結尾 | |
\b | 單詞邊界 | /\bis/ 匹配以 is 開頭的單詞 |
\B | 非單詞邊界 | /\Bis/ 匹配 This 中的 is |
\d | 數字 [0-9] | |
\D | 非數字 [^0-9] | |
\w | 字母數字底線 [0-9a-zA-Z_] | |
\W | 非字母數字底線 | |
\s | 空白字元 [\f\t\v] | |
\S | 非空白字元 |
// 捕獲組:括號內匹配內容存入 $1, $2...
// 日期格式驗證:要求分隔符一致
/^\d{2}([\W])\d{2}\1\d{4}$/ // 匹配 12-31-2006、09/27/1996,不匹配 12/34-5678
// 非捕獲組 (?:...):不佔用反向引用編號
/(?:a|b|c)(D|E|F)\1g/ // 匹配 aEEg,\1 指向 (D|E|F)
preg_match() / preg_match_all():匹配/全局匹配,回傳次數,結果存入第三參數陣列。preg_quote():轉義字串中所有正則特殊字元,動態構建模式必用。preg_split():正則分割字串,比 explode 強大。preg_grep():以正則過濾陣列元素。preg_replace() / preg_replace_callback():替換/回調替換,**棄用 /e 修飾符**。$str = '...ACTION="ASDF.BPHP"... ACTION="HTTP: test.php?..."...';
preg_match_all('/\s+action="(?!http:)(.*?)"\s/i', $str, $match);
// $match[1] 含相對路徑 action 值
function search($url, $match) {
return $url . '/' . $match;
}
$str = preg_replace('/(?<=\saction=")(?!http:)(.*?)(?="\s)/e', 'search($url, "$1")', $str);
// 現代寫法:preg_replace_callback
$str = preg_replace_callback(
'/(?<=\saction=")(?!http:)(.*?)(?="\s)/',
function($m) use ($url) { return $url . '/' . $m[1]; },
$str
);
$str = 'xxxxxx.com.cn bold font paragraph text
';
preg_match_all('/(?<=<(\w{1})>).*?(?=<\/\1>)/', $str, $match);
// 匹配 與 內容,利用反向引用 \1 確保標籤配對
$form_html = preg_replace(
'/(?<=\saction="|\ssrc="|\shref=")(?!http:|javascript)(.*?)(?="\s)/e',
'add_url($url, "$1")',
$form_html
);
// 同樣建議改用 preg_replace_callback
explode,效能遠超正則。u 修飾符處理 UTF-8,避免中文亂碼。(a*)*)導致災難性回溯。