正則表達式 是文字處理的瑞士刀,PHP 採用 PCRE (Perl Compatible Regular Expressions) 引擎,功能強大且效能優異。本文從基礎語法、修飾符、進階斷言、實戰範例到效能優化,系統整理 PHP 正則完整知識體系。
| 元字元 | 說明 | 範例 |
|---|---|---|
. | 任意單一字元 (除換行) | a.c 匹配 abc, axc |
\d | 數字 [0-9] | \d{3} 三位數 |
\D | 非數字 | |
\w | 單字字元 [a-zA-Z0-9_] | |
\W | 非單字字元 | |
\s | 空白字元 [\t\n\r\f\v] | |
\S | 非空白字元 | |
^ | 字串開頭 (多行模式下為行首) | |
$ | 字串結尾 (多行模式下為行尾) | |
| | 或運算 | cat|dog |
() | 捕獲群組 (編號 1,2...) | (\d{4})-(\d{2}) |
(?:) | 非捕獲群組 | (?:\d{3})?- |
(?P | 命名捕獲群組 | (?P |
[] | 字元類別 | [aeiou] |
[^] | 排除字元類別 | [^0-9] |
* | 0 次或多次 (貪婪) | |
+ | 1 次或多次 | |
? | 0 次或 1 次 | |
{n,m} | n 到 m 次 | \d{3,5} |
*?, +?, ?? | 惰性量詞 (最少匹配) |
$pattern = '/^https?:\/\/([\w.]+)\/([\w-]+)\.html$/i'; // ^ 定界符 (可用 / # ~ @ 等) // i 忽略大小寫 // m 多行模式 (^$ 匹配行首尾) // s 單行模式 (. 匹配換行) // x 忽略模式中的空白/註解 (可讀性) // u UTF-8 模式 (正確處理中文) // A 強制從字串開頭匹配 // D $ 僅匹配字串絕對結尾 // U 反轉貪婪/惰性預設行為
建議: 含 / 時用 # 定界符;處理中文務必加 u 修飾符。
| 語法 | 名稱 | 方向 | 條件 | 範例 |
|---|---|---|---|---|
(?=...) | 正向前瞻 | 向右 | 後面必須匹配 | \d(?=px) 匹配後面是 px 的數字 |
(?!...) | 負向前瞻 | 向右 | 後面不可匹配 | \d(?!px) 匹配後面非 px 的數字 |
(?<=...) | 正向後瞻 | 向左 | 前面必須匹配 | (?<=\$)\d+ 匹配 $ 後的數字 |
(? | 負向後瞻 | 向左 | 前面不可匹配 | (? 匹配非 $ 開頭的數字 |
特性: 零寬度、不消耗字元、不捕獲、可嵌套。
| 函數 | 用途 | 回傳值 |
|---|---|---|
preg_match() | 單次匹配 | int (0/1/false),$matches 參考捕獲 |
preg_match_all() | 全域匹配 | int 匹配次數,$matches 結構不同 |
preg_replace() | 搜尋替換 | 字串/陣列,$limit 限制次數 |
preg_replace_callback() | 回調替換 | 字串,回調函數處理複雜邏輯 |
preg_split() | 正則分割 | 陣列,$limit, $flags |
preg_quote() | 跳脫特殊字元 | 字串,用於動態建構模式 |
preg_grep() | 陣列過濾 | 陣列,返回匹配元素 |
preg_last_error() | 取得最後錯誤碼 | int (PREG_NO_ERROR 等) |
$emailRegex = '/^[a-zA-Z0-9.!#$%&*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/';
if (preg_match($emailRegex, $email)) { /* valid */ }
$text = '訪問 https://example.com/path 和 https://sub.test.org';
preg_match_all('#https?://(?P[\w.-]+)#', $text, $matches);
print_r($matches['domain']); // ['example.com', 'sub.test.org']
$pwdRegex = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/';
if (preg_match($pwdRegex, $pwd)) { /* strong */ }
$html = ''; preg_match_all('/(\w+)="([^"]*)"/', $html, $m, PREG_SET_ORDER); foreach ($m as $attr) { echo $attr[1] . '=' . $attr[2] . PHP_EOL; }
$text = '你好!這是測試。包含英文, 和數字123。';
$sentences = preg_split('/(?<=[。!?!?])/u', $text, -1, PREG_SPLIT_NO_EMPTY);
(a+)+、(.*)* 遇到長字串會指數級爆炸 → 使用具體字元類別、限制量詞、原子群組 (?>...)。strpos()、str_contains() (PHP 8)、substr() 效能遠優於正則。ini_set('pcre.backtrack_limit', 100000); (預設 1M)。ini_set('pcre.jit', 1); 開啟即時編譯。[] 未閉合。preg_last_error(),常見為 PREG_BACKTRACK_LIMIT_ERROR (回溯過深) 或 PREG_RECURSION_LIMIT_ERROR。