正則表達式是字串處理利器,但語法晦澀、效能陷阱多。本文整理 30+ 高頻實戰模式,涵蓋數字、字串、日期、網路、身分證、IP、HTML、編碼等類別,並說明優化技巧、常見陷阱與 PHP 具體用法。
一、數字驗證類
| 名稱 | 模式 | 說明 |
| 非負整數 (含 0) | ^\d+$ | /^\d+$/ 或 ctype_digit() 更快 |
| 正整數 (不含 0) | ^[1-9]\d*$ | |
| 整數 (含負數) | ^-?\d+$ | |
| 非負浮點數 | ^\d+(\.\d+)?$ | 允許 123. 若不允許用 ^\d+(\.\d+)?$ |
| 正浮點數 | ^(([1-9]\d*|0)\.\d*[1-9])|([1-9]\d*)$ | 較複雜,建議 filter_var($v, FILTER_VALIDATE_FLOAT) + > 0 |
| 浮點數 (含負數) | ^-?\d+(\.\d+)?$ | |
| 金額 (兩位小數) | ^\d+(\.\d{1,2})?$ | 或 ^\d+(\.\d{2})?$ 強制兩位 |
二、字串格式類
| 名稱 | 模式 | 說明 |
| 純英文字母 | ^[A-Za-z]+$ | |
| 大寫英文 | ^[A-Z]+$ | |
| 小寫英文 | ^[a-z]+$ | |
| 英數字 | ^[A-Za-z0-9]+$ | |
| 英數字+底線 | ^\w+$ | \w = [A-Za-z0-9_] |
| 中文字符 | ^[\x{4e00}-\x{9fa5}]+$ | 需 u 修飾符:/^[\x{4e00}-\x{9fa5}]+$/u |
| 雙位元組字符 (含中文) | ^[\x80-\xff]+$ | 非 ASCII |
| 用戶名 (字母開頭,5-16 字元,英數底線) | ^[A-Za-z][A-Za-z0-9_]{4,15}$ | |
| 強密碼 (8-20 字,含大小寫、數字、特殊符號) | ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$ | 正向預查 |
三、網路與聯絡類
| 名稱 | 模式 | 說明 |
| Email (RFC 5322 簡化版) | ^[\w.+-]+@[\w-]+\.[\w.-]+$ | 實務建議 filter_var($email, FILTER_VALIDATE_EMAIL) |
| URL (HTTP/HTTPS) | ^https?://[\w.-]+(?:\.[\w.-]+)+[^\s]*$ | 或 filter_var($url, FILTER_VALIDATE_URL) |
| 國內電話 (含區碼) | ^(0\d{2,3}-?)?\d{7,8}$ | 如 02-12345678, 0755-12345678 |
| 手機號 (台灣) | ^09\d{8}$ | |
| 手機號 (大陸) | ^1[3-9]\d{9}$ | |
| QQ 號 | ^[1-9]\d{4,10}$ | 5-11 位,首位非 0 |
| IPv4 | ^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(25[0-5]|2[0-4]\d|[01]?\d?\d)$ | 或 filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) |
| IPv6 | ^([\da-f]{1,4}:){7}[\da-f]{1,4}$ | 簡化版,完整版極複雜,用 FILTER_FLAG_IPV6 |
| MAC 位址 | ^([\da-f]{2}[:-]){5}[\da-f]{2}$ | i 修飾符 |
四、日期時間類
| 名稱 | 模式 | 說明 |
| YYYY-MM-DD | ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ | 僅格式,實際有效性用 DateTime 驗證 |
| YYYY/MM/DD | ^\d{4}/(0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01])$ | |
| HH:MM:SS (24小時) | ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$ | |
| ISO 8601 日期時間 | ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?$ | |
五、身分證與特定編號 (台灣/大陸)
| 名稱 | 模式 | 說明 |
| 台灣身分證字號 | ^[A-Z][12]\d{8}$ | 格式驗證,完整檢查碼需演算法 |
| 大陸身分證 (18位) | ^\d{6}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$ | 格式驗證,檢查碼需演算法 |
| 統一編號 (台灣公司) | ^\d{8}$ | 格式,邏輯驗證需加權加總 |
| 信用卡 (Luhn 算法前置格式) | ^\d{13,19}$ | 實際驗證需 Luhn 算法 |
六、HTML/標記處理類
| 名稱 | 模式 | 說明 |
| 匹配 HTML 標籤 | /<([^>]+)>.*?<\/\1>|<[^>]+\/>/s | 貪婪/非貪婪陷阱多,**建議用 DOMDocument** |
| 移除 HTML 標籤 | strip_tags($str) | 內建函式更安全 |
| 匹配屬性值 | /(\w+)=(["'])(.*?)\2/ | |
| 匹配空白行 | /^\s*$/m | m 多行模式 |
| 首尾空白 | /^\s+|\s+$/g | 或 trim() |
七、PHP 正則最佳實踐
1. 使用正確分隔符與修飾符
// 好的分隔符:~ # @ % 避免需跳脫 /
$pattern = '~^\d{4}-\d{2}-\d{2}$~';
// 修飾符
$pattern = '/pattern/iu'; // i=不分大小寫, u=UTF-8, s=單行模式(.匹配換行), m=多行模式(^$匹配行首尾)
2. 優先使用內建函式
// Email
filter_var($email, FILTER_VALIDATE_EMAIL);
// URL
filter_var($url, FILTER_VALIDATE_URL);
// IP
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
// 數字
ctype_digit($str), is_numeric($val), filter_var($val, FILTER_VALIDATE_FLOAT)
// HTML 標籤移除
strip_tags($html)
// 空白修剪
trim($str)
3. 效能優化技巧
- 避免過度使用
.* 或 .+ (貪婪匹配導致回溯爆炸),改用 [^x]* 或 .+? (非貪婪)
- 錨定 ^ $:固定開頭結尾,減少匹配嘗試
- 預編譯重用:靜態變數儲存編譯後模式 (PCRE 內部快取),避免迴圈中重複
preg_match
- 具體化字符類:
\d 比 [0-9] 快 (視 PCRE 版本),[a-z] 比 \w 窄更快
- 原子群組
(?>...):禁止回溯,固定匹配失敗即回溯
4. 常見陷阱
// 陷阱 1:貪婪匹配吞掉預期內容
$html = 'a
b
';
preg_match('/.*<\/div>/', $html, $m); // 匹配整個字串!
// 正確:非貪婪或具體化
preg_match('/
.*?<\/div>/', $html, $m); //
a
preg_match('/
[^<]*<\/div>/', $html, $m); // 更快
// 陷阱 2:修飾符遺漏 u 導致中文截斷
$str = '測試';
preg_match('/^../', $str); // 可能匹配到半個中文字元 (2 bytes)
preg_match('/^../u', $str); // 正確匹配 2 個字元
// 陷阱 3:preg_replace 無限迴圈 (替換後仍匹配模式)
$str = 'a';
$str = preg_replace('/a/', 'aa', $str); // 無限增長!
// 正確:使用限制次數或檢查變化
5. 實用工具函式
// 安全 preg_match 封裝
function regexMatch(string $pattern, string $subject, int $flags = 0, int $offset = 0): ?array {
$result = @preg_match($pattern, $subject, $matches, $flags, $offset);
if ($result === false) {
throw new RuntimeException("PCRE 錯誤: " . preg_last_error_msg());
}
return $result ? $matches : null;
}
// 批次替換 (避免順序干擾)
function multiReplace(array $patterns, string $subject): string {
// 依模式長度降序,避免短模式先匹配干擾長模式
uksort($patterns, fn($a, $b) => strlen($b) <=> strlen($a));
return preg_replace(array_keys($patterns), array_values($patterns), $subject);
}
八、線上測試工具推薦
九、總結
正則三原則:
1. **能用內建函式就不用正則** (filter_var, ctype_*, strip_tags, trim, parse_url)
2. **能用具體字符類就不用 .*** (避免回溯災難)
3. **必加 u 修飾符處理 UTF-8**,錨定 ^$,善用線上工具驗證效能與正確性
- 上一篇文章: PHP + jQuery Ajax 非同步檔案上傳完整實作 (含進度條、多檔、拖曳)
- 下一篇文章: PHP 常見錯誤總結與除錯技巧大全 (新手必讀)