正則表達式是字串模式比對、擷取、替換的利器。PHP 提供兩套函式庫:PCRE(Perl Compatible Regular Expressions) 以 preg_* 為前綴,功能強大且與 Perl 相容;POSIX 以 ereg_* 為前綴,自 PHP 5.3 棄用,PHP 7.0 移除。本文聚焦 PCRE 實戰應用。
模式以分隔符包裹,常用 /,如 /apple/i。分隔符可為任意非字母數字、非反斜線、非空白字元(如 #、~、%)。
| 元字符 | 說明 | 等價類別 |
|---|---|---|
\A | 字串開頭 | — |
\Z | 字串結尾(忽略末尾換行) | — |
\b | 單字邊界 | — |
\B | 非單字邊界 | — |
\d | 數字 | [0-9] |
\D | 非數字 | [^0-9] |
\w | 字母、數字、底線 | [0-9a-zA-Z_] |
\W | 非單字字元 | [^0-9a-zA-Z_] |
\s | 空白字元 | [\f\t\v\n\r] |
\S | 非空白字元 | [^\f\t\v\n\r] |
i:大小寫不敏感m:多行模式(^/$ 匹配行首尾)s:單行模式(. 匹配換行)x:忽略模式中的空白與註解u:UTF-8 模式(處理中文必備)U:貪婪模式反轉(預設非貪婪)e:preg_replace 替換字串作為程式碼執行(已棄用,改用 preg_replace_callback)(...):捕獲群組,可用 \1、\2... 反向引用。(?:...):非捕獲群組,不佔用反向引用編號,效能略優。(?P...) ,引用用 \k 或 \g{name}。| 函式 | 用途 |
|---|---|
preg_match | 執行一次匹配,回傳 0/1,第三參數接收捕獲結果 |
preg_match_all | 全域匹配,回傳匹配次數,第三參數接收多維陣列 |
preg_replace | 搜尋並替換,支援回呼函式 |
preg_split | 依正則分割字串為陣列 |
preg_grep | 過濾陣列中匹配模式的元素 |
preg_quote | 轉義字串中所有正則特殊字元 |
$str = '<form action="/login"><form action="https://evil.com">';
preg_match_all('/\s+action="(?!http:)(.*?)"/', $str, $matches);
// $matches[1] = ['/login']
function search($url, $match) { return $url . '/' . $match; }
$str = '<form action="user/login">';
$str = preg_replace('/(?<=\saction=")(?!http:)(.*?)(?="\s)/', 'search("https://api.example.com", "$1")', $str);
// 結果:
$str = '<b>bold</b> <font color="red">text</font>';
preg_match_all('/(?<=<(\w{1})>).*(?=<\/1>)/', $str, $matches);
// 僅匹配 bold 的 "bold"
$form_html = preg_replace(
'/(?<=\saction="|\ssrc="|\shref=")(?!http:|javascript)(.*?)(?="\s)/',
'add_url($url, "$1")',
$form_html
);
正則功能強大但編寫除錯成本高。簡單字串切割優先用 explode、strpos、substr;複雜驗證、擷取才用正則。PCRE 執行效率通常優於 POSIX,且語法與 Perl/JS 相通,學習投資回報率最高。