正則表達式修飾符(Pattern Modifiers)控制匹配行為,是寫出精準、高效正則的關鍵。本文系統講解 PCRE 所有修飾符含義、組合技巧、常見誤區,附實戰代碼驗證。
| 修飾符 | 常量 | 作用 | 典型場景 |
|---|---|---|---|
| i | PCRE_CASELESS | 忽略大小寫匹配 | 關鍵詞搜索、郵箱驗證 |
| s | PCRE_DOTALL | 單行模式:點號 . 匹配任意字符含換行符 | 多行文本提取、HTML 標籤跨行匹配 |
| m | PCRE_MULTILINE | 多行模式:^ 匹配行首、$ 匹配行尾(而非字符串首尾) | 逐行處理日誌、代碼分析 |
| x | PCRE_EXTENDED | 忽略模式中的空白字符,支持 # 註釥 | 編寫可讀性強的複雜正則 |
| U | PCRE_UNGREEDY | 反轉貪婪:量詞默認非貪婪,加 ? 變貪婪 | 提取最短匹配、避免過度匹配 |
| A | PCRE_ANCHORED | 強制錨定:僅從字符串開頭開始匹配(等價 ^) | 性能優化、精確前綴匹配 |
| D | PCRE_DOLLAR_ENDONLY | $ 僅匹配字符串絕對結尾(不匹配末尾換行前) | 嚴格結尾校驗 |
| u | PCRE_UTF8 | UTF-8 模式:按 Unicode 字符而非字節匹配 | 中文/Emoji/多語言文本處理 |
| J | PCRE_DUPNAMES | 允許重複命名子組 (?<name>...) | 複雜分組別名複用 |
$html = "<div>\n 內容\n</div>";
// 無 s:失敗
preg_match('/<div>.+<\/div>/', $html, $m); // null
// 有 s:成功
preg_match('/<div>.+<\/div>/s', $html, $m); // 匹配整個跨行块
$code = "function foo() {\n return 1;\n}";
// 無 m:^ 只匹配字符串開頭
preg_match_all('/^\s*\w+/m', $code, $m); // ['function', 'return']
// 有 m:^ 匹配每行開頭
preg_match_all('/^\s*\w+/', $code, $m); // ['function']
$str = 'abceadeddd';
// 貪婪(默認):匹配最長
preg_match('/a.+e/', $str, $m); // 'abceade'
preg_match('/a.+e/U', $str, $m); // 'abce' (U 反轉)
// 等價寫法:具體量詞非貪婪
preg_match('/a.+?e/', $str, $m); // 'abce' (推薦,語義清晰)
$zh = '你好世界';
// 無 u:按字節匹配,. 匹配半個中文字符
preg_match_all('/./', $zh, $m); // 6 個字節片段
preg_match_all('/./u', $zh, $m); // 4 個字符 ['你','好','世','界']
// 邊界 \b 在中文需配合 u
preg_match('/\b世\b/u', $zh); // 正確匹配單詞邊界
$regex = '/
^ # 字符串開始
(?P\d{4}) # 年份
-
(?P\d{2}) # 月份
-
(?P\d{2}) # 日期
$ # 字符串結尾
/x';
preg_match($regex, '2024-01-15', $m);
// $m['year']='2024', $m['month']='01', $m['day']='15'
m 與 D 衝突:m 開啟時 D 無效U 與具體量詞 *? +? 疊加:U 會反轉 ? 行為,導致混淆,避免同時使用(?is) 可在模式中局部開啟,優先級高於外部修飾符| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
| preg_match('/\d+/', $utf8) | 中文數字未匹配 | 加 u 修飾符 |
| preg_replace('/.+/', '', $multiLine) | 只匹配第一行 | 加 s 修飾符 |
| preg_match('/^item$/', $list) | 只匹配第一行 | 加 m 修飾符 |
| preg_match('/a.+e/U', $str) | U 導致 +? 變貪婪 | 移除 U,用 a.+?e |
// 1. 使用在線測試工具:regex101.com (支持 PCRE/PHP) // 2. PHP 內置調試 $re = '/pattern/isu'; var_dump(preg_match($re, $subject, $m, PREG_OFFSET_CAPTURE)); // 3. 獲取編譯後的正則信息 (需 PCRE 8.20+) $pcre_info = pcre_get_compiled_regex_info($re);
修飾符是正則表達式的「開關面板」,精通其組合效應,能讓你用最少代碼解決最複雜的文本匹配問題。