首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 中文正則表達式完全指南:GBK 與 UTF-8 雙編碼實戰

     編輯:PHP 相關知識

正則匹配中文是表單驗證、內容過濾、數據清洗的高頻需求。但 GBK 與 UTF-8 編碼下中文匹配模式截然不同,搞混極易導致匹配失效或誤傷。本文系統整理雙編碼下的中文正則模式與實戰代碼。

編碼本質差異

編碼中文編碼範圍字節數正則策略
GBK/GB2312高位字節 0x81-0xFE,低位 0x40-0xFE(除 0x7F)雙字節按字節範圍匹配:[\x81-\xFE][\x40-\xFE]
UTF-8基本多文種平面 (BMP) 中日韓統一表意文字:U+4E00-U+9FA5三字節按 Unicode 碼點匹配:[\x{4e00}-\x{9fa5}] 需 u 修飾符

GBK 編碼下中文正則

1. 判斷字符串是否全為中文

<?php
$str = '全部是漢字測試';
// ^ 開頭 $ 結尾 + 一次或多次
if (preg_match('/^([\x81-\xFE][\x40-\xFE])+$/', $str)) {
    echo '全部是漢字';
} else {
    echo '不全是漢字';
}
// 輸出:全部是漢字

$str2 = 'all全部是漢字測試';
if (preg_match('/^([\x81-\xFE][\x40-\xFE])+$/', $str2)) {
    echo '全部是漢字';
} else {
    echo '不全是漢字';
}
// 輸出:不全是漢字
?>

2. 判斷字符串是否包含中文

<?php
$str = '漢字3測試';
if (preg_match('/([\x81-\xFE][\x40-\xFE])/', $str)) {
    echo '含有漢字';
} else {
    echo '不含有漢字';
}
// 輸出:含有漢字

$str2 = 'abc345';
if (preg_match('/([\x81-\xFE][\x40-\xFE])/', $str2)) {
    echo '含有漢字';
} else {
    echo '不含有漢字';
}
// 輸出:不含有漢字
?>

注意:GBK 正則基於字節特徵,**與源文件編碼無關**,只要輸入字符串實際為 GBK 編碼即可匹配。

UTF-8 編碼下中文正則

**核心要求**:正則必須加 u 修飾符(PCRE_UTF8),否則按單字節解析導致錯誤。

1. 判斷純中文字符串

<?php
$str = "php編程";
// \x{4e00}-\x{9fa5} 覆蓋常用漢字 20902 個
if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $str)) {
    echo "該字符串全部是中文";
} else {
    echo "該字符串不全部是中文";
}
// 輸出:該字符串不全部是中文(含 php)
?>

2. 匹配提取所有中文

<?php
$str = "PHP中文正則表達式教程2024";
preg_match_all('/[\x{4e00}-\x{9fa5}]+/u', $str, $matches);
print_r($matches[0]);
/*
Array
(
    [0] => 中文正則表達式教程
)
*/
?>

3. 替換/過濾非中文

<?php
$str = "用戶名:張三_123";
// 保留中文、數字、下劃線,其余替換為空
$clean = preg_replace('/[^\x{4e00}-\x{9fa5}0-9_]/u', '', $str);
echo $clean; // 輸出:張三_123
?>

進階:擴展中文範圍

U+4E00-U+9FA5 僅覆蓋基本漢字。若需支持生僻字、擴展區、日韓漢字,可擴展範圍:

<?php
// 擴展範圍(根據業務按需組合)
$patterns = [
    '基本漢字'       => '\x{4e00}-\x{9fa5}',
    '擴展A區'        => '\x{3400}-\x{4dbf}',
    '擴展B區'        => '\x{20000}-\x{2a6df}',
    '擴展C區'        => '\x{2a700}-\x{2b73f}',
    '擴展D區'        => '\x{2b740}-\x{2b81f}',
    '擴展E區'        => '\x{2b820}-\x{2ceaf}',
    '兼容補充區'     => '\x{f900}-\x{faff}',
    'CJK 部首補充'   => '\x{2e80}-\x{2eff}',
    '康熙部首'       => '\x{2f00}-\x{2fdf}',
];

// 組合正則(示例:基本+擴展A+兼容)
$han_regex = '/[' . implode('', array_slice($patterns, 0, 3)) . ']+/u';
?>

編碼檢測與轉換最佳實踐

<?php
// 1. 檢測編碼
$encoding = mb_detect_encoding($str, ['UTF-8', 'GBK', 'GB2312', 'ASCII'], true);

// 2. 統一轉為 UTF-8 再處理(推薦)
if ($encoding !== 'UTF-8') {
    $str = mb_convert_encoding($str, 'UTF-8', $encoding);
}

// 3. 使用 UTF-8 正則統一處理
if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $str)) {
    // ...
}
?>

常見坑點避雷

  • 忘記 u 修飾符:UTF-8 正則必須加 /u,否則按字節匹配產生亂碼結果。
  • 源文件編碼與正則不一致:PHP 文件保存為 UTF-8,正則中直接寫中文需確保文件編碼一致,建議統一用 Unicode 轉義 \x{4e00} 避免編碼困擾。
  • GBK 正則用於 UTF-8 字符串:會誤匹配 UTF-8 中文字節中的高位字節,產生大量假陽性。
  • 範圍不全導致生僻字匹配失敗:人名、地址常含生僻字,按需擴展 Unicode 範圍。

總結

**UTF-8 統一用 /[\x{4e00}-\x{9fa5}]/u,GBK 用 /[\x81-\xFE][\x40-\xFE]/**。生產環境強烈建議**統一轉 UTF-8 後再用 UTF-8 正則**,消除編碼不一致帶來的所有隱患。掌握 Unicode 碼點範圍與 u 修飾符,是處理中文正則的核心鑰匙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved