PCRE vs POSIX
PHP 5.3+ 棄用 POSIX 正則 (ereg_*),統一使用 PCRE (Perl Compatible Regular Expressions),函數前綴 preg_*。
界定符與修飾符
// 合法界定符:非字母數字、非反斜槓、非空白字符
/pattern/i # 正斜線(最常用)
#pattern# # 雜湊符號(含正斜線時便利)
~pattern~ # 波浪號(含 URL 時便利)
%pattern% # 百分號
{pattern} # 大括號
// 常用修飾符(寫在結束界定符後)
i // 不區分大小寫
m // 多行模式:^$ 匹配行首行尾
s // 單行模式:. 匹配換行符
x // 忽略模式空白(可寫註釋)
u // UTF-8 模式(處理中文必加)
U // 反轉貪婪/非貪婪
J // 允許重複子組名 (?J)
A // 強制從目標字符串開頭匹配
D // $ 僅匹配字符串末尾(不匹配末尾換行前)
核心元字符速查
| 字符 | 含義 |
\ | 轉義 / 元序列前綴 |
^ | 字符串/行開頭 |
$ | 字符串/行結尾 |
. | 除換行外任意字符 (加 s 含換行) |
[...] | 字符類 |
[^...] | 否定字符類 |
| | 分支/或 |
(...) | 捕獲組 |
(?:...) | 非捕獲組 |
(?<name>...) | 命名捕獲組 |
\1, \k<name> | 反向引用 |
量詞與貪婪模式
| 量詞 | 含義 | 非貪婪版 |
* | 0 次或多次 {0,} | *? |
+ | 1 次或多次 {1,} | +? |
? | 0 次或 1 次 {0,1} | ?? |
{n} | 恰好 n 次 | {n}? |
{n,} | 至少 n 次 | {n,}? |
{n,m} | n 到 m 次 | {n,m}? |
斷言(零寬斷言)
// 預瞻(向後看)
(?=pattern) // 正向預瞻:後面必須匹配 pattern
(?!pattern) // 負向預瞻:後面不能匹配 pattern
// 後瞻(向前看)-- 固定寬度
(?<=pattern) // 正向後瞻:前面必須匹配 pattern
(?<!pattern) // 負向後瞻:前面不能匹配 pattern
// 實例:匹配不被引號包圍的逗號
/(?
預定義字符類
| 簡寫 | 等價 | 說明 |
\d | [0-9] | 數字 |
\D | [^0-9] | 非數字 |
\w | [a-zA-Z0-9_] | 單詞字符 |
\W | [^a-zA-Z0-9_] | 非單詞字符 |
\s | [\s\t\r\n\f\v] | 空白字符 |
\S | [^\s\t\r\n\f\v] | 非空白 |
\h | [\s\t] | 水平空白 (PHP 5.2.4+) |
\v | [\r\n\f\v] | 垂直空白 (PHP 5.2.4+) |
PCRE 核心函數速查
| 函數 | 用途 | 返回值 |
preg_match | 單次匹配 | int (0/1/false) |
preg_match_all | 全局匹配 | int (匹配次數) |
preg_replace | 搜索替換 | string/array |
preg_replace_callback | 回調替換 | string/array |
preg_split | 正則分割 | array |
preg_grep | 數組過濾 | array |
preg_quote | 轉義正則元字符 | string |
preg_last_error | 獲取最後錯誤碼 | int |
preg_filter | 過濾並替換 | array |
實戰模式庫
// Email (RFC 5322 簡化版)
/^[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])?)+$/
// 手機號(中國大陸)
/^1[3-9]\d{9}$/
// 身份證號(18 位,含校驗碼邏輯需代碼驗證)
/^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/
// URL
/^https?:\/\/[^\s\/$.?#].[^\s]*$/i
// IPv4
/^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
// HTML 標簽(含屬性)
/<([a-z]+)([^>]*)>(.*?)<\/\1>/is
// 密碼強度:8-20 位,含大小寫、數字、特殊符號
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/
性能優化原則
- 優先使用具體字符類代替
.
- 避免嵌套量詞
(a+)+ 導致災難性回溯
- 使用非捕獲組
(?:...) 減少內存
- 錨點
^ $ 縮小搜索範圍
- 預編譯複用:
$re = '/pattern/u'; preg_match($re, $str);
- 超長字符串考慮
preg_match_all 分塊處理