PHP 5.3 起,POSIX 正則系列函數(ereg、eregi、ereg_replace 等)被標記為 Deprecated(棄用),執行時會拋出 E_DEPRECATED 錯誤;PHP 7.0 徹底移除這些函數。遷移到 PCRE 系列(preg_match、preg_replace 等)是必經之路。
| 特性 | POSIX (ereg) | PCRE (preg) |
|---|---|---|
| 定界符 | 無 | 必須成對,如 /pattern/、#pattern# |
| 大小寫敏感 | ereg 敏感,eregi 不敏感 | 統一用 i 修飾符:/pattern/i |
| 元字符 | 較少(如 \d 不支持) | 豐富(\d、\w、\s、. 等) |
| 性能 | 較慢 | 更快(JIT 編譯優化) |
| 錯誤處理 | 返回 false | 返回 false,preg_last_error() 獲取詳情 |
所有正則模式必須包裹在定界符中,常用 /.../ 或 #...#(含正斜杠時推薦):
// 遷移前
ereg('^[0-9]+$', $str);
// 遷移後
preg_match('/^[0-9]+$/', $str);
// 遷移前
eregi('keyword', $str);
// 遷移後
preg_match('/keyword/i', $str);
PCRE 中 .、*、?、+、(、)、[、]、{、}、^、$、|、\ 等均為元字符,需轉義:
// 遷移前:匹配字面 "file.php"
ereg('file.php', $str);
// 遷移後:點號需轉義
preg_match('/file\.php/', $str);
function inject_check($sql_str) {
$sql_str = strtolower($sql_str);
return eregi('fopen|post|eval|select|insert|and|or|update|delete|\'|/\*|\*|\.\./|\./|union|into|load_file|outfile', $sql_str);
}
function inject_check($sql_str) {
$sql_str = strtolower($sql_str);
// 使用 # 定界符避免正斜杠衝突,單引號在雙引號字符串中無需轉義
$pattern = '#fopen|post|eval|select|insert|and|or|update|delete|\'|/\*|\*|\.\./|\./|union|into|load_file|outfile#i';
return (bool)preg_match($pattern, $sql_str);
}
#...#,避免模式中 / 需大量轉義。i 修飾符替代 eregi,代碼更清晰。bool,語義明確(preg_match 返回 0/1/false)。// POSIX: [:alnum:] 字母數字
ereg('[[:alnum:]]+', $str);
// PCRE: \w 或 [a-zA-Z0-9_]
preg_match('/\w+/', $str);
PCRE 預設貪婪,.*? 為非貪婪;POSIX 無此概念,行為差異大,遷移時需實測。
ereg_replace → preg_replace// 遷移前
ereg_replace('(\d{4})-(\d{2})', '\\2/\\1', $date);
// 遷移後:反向引用用 $n 而非 \n
preg_replace('/(\d{4})-(\d{2})/', '$2/$1', $date);
ereg 調用。EregToPregRector 規則一鍵遷移全項目。ereg\((['\"])(.+?)\1 → 替換:preg_match('/$2/',(需人工核對)。// 測試:匹配 100 萬次簡單模式
// preg_match: ~0.45s
// ereg (PHP 5.2): ~1.2s
// 結論:PCRE 快 2-3 倍,且內存佔用更低
@ereg() 抑制錯誤的做法,這只掩蓋問題,不解決兼容性。完成遷移後,代碼將兼容 PHP 7/8 全系列,性能提升,並擁抱現代正則生態的強大功能(命名捕獲組、斷言、遞歸模式等)。