在 PHP 中使用正則表達式匹配中文,常因編碼與 PCRE 語法差異而踩坑。本文從常見錯誤出發,逐步推導出 UTF-8 環境下正確匹配中文(CJK 統一表意文字)的模式,並整理常用編碼範圍對照表。
// 錯誤 1:直接使用 \u4e00-\u9fa5(PCRE 不支援 \u)
preg_match("/^[\u4e00-\u9fa5_a-zA-Z0-9]{3,15}$/", $str);
// Warning: PCRE does not support \u at offset 3
// 錯誤 2:使用 \x{...} 但範圍錯誤(複製自 JS 的 0x2460-0x2468 非中文區)
preg_match('/^[\x{2460}-\x{2468}]+$/u', $str); // 匹配的是圈字數字 ①②…
// 錯誤 3:十六進制寫法缺少大括號
preg_match("/^[\x4e00-\x9fa5]+$/u", $str);
// Warning: invalid UTF-8 string at offset 6
PCRE 在 u 修飾符下支援 \x{HEX} 表示 Unicode 碼位。中文基本區為 U+4E00 ~ U+9FA5(CJK Unified Ideographs):
// 純中文判斷
if (preg_match("/^[\x{4e00}-\x{9fa5}]+$/u", $str)) {
echo "全為中文";
}
// 中英數混合(如用戶名驗證)
if (preg_match("/^[\x{4e00}-\x{9fa5}a-zA-Z0-9_]{3,15}$/u", $str)) {
echo "合法";
}
\x{3400}-\x{4DBF}(罕用字)\x{F900}-\x{FAFF}\x{20000}-\x{2EBEF}(需 PHP 7.3+ 且編譯 PCRE2 才能正確處理補充平面)實務上若需涵蓋生僻字,建議使用 \p{Han}(Unicode Script 屬性,PHP 7.3+ PCRE2 支援):
// 現代最簡潔寫法(需 PHP 7.3+)
if (preg_match('/^\p{Han}+$/u', $str)) { ... }
若專案仍使用 GBK/Big5,可用單位元組範圍近似判斷(非嚴格):
// GBK/GB2312 中文區近似
if (preg_match("/^[\x80-\xff]+$/", $str)) { ... }
// Big5 中文區近似
if (preg_match("/^[\x81-\xfe][\x40-\x7e\xa1-\xfe]+$/", $str)) { ... }
| 文字系統 | Unicode 範圍 | 備註 |
|---|---|---|
| 中文 (CJK 基本區) | U+4E00 ~ U+9FA5 | 最常用 20,902 字 |
| 中文擴展 A | U+3400 ~ U+4DBF | 罕用字 |
| 韓文諺文音節 | U+AC00 ~ U+D7A3 | 完整音節 |
| 日文平/片假名 | U+3040 ~ U+309F / U+30A0 ~ U+30FF | |
| 日文漢字 | U+4E00 ~ U+9FA5 (共用) |
\uXXXX,必須用 \x{XXXX} 搭配 u 修飾符。/^[\x{4e00}-\x{9fa5}]+$/u。\p{Han} 一行解決所有漢字。