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

PHP 過濾字符串中中文與數字:基於編碼特徵的提取函數實現

     編輯:PHP 相關知識

PHP 過濾字符串中中文與數字:基於編碼特徵的提取函數實現

針對特定編碼環境下從混合字符串中提取中文字符的需求,本文提供一個基於字節高位特徵判斷的函數 getChinese(),支援 GBK/GB2312/UTF-8/UTF-16 多種編碼,同時保留數字字符。

核心原理

  • 中文字符特徵:多字節編碼中,首字節高位為 1 (即 ≥ 0xA0 = 160)
  • 編碼字節長度:GBK=2, GB2312=3, UTF-8=3, UTF-16=4
  • 數字判斷:ASCII 0-9 直接保留

完整函數實現

<?php
/**
 * 從字符串提取中文字符及數字
 * @param string $string 輸入字符串
 * @param string $encode 編碼類型: GBK, GB2312, UTF-8, UTF-16
 * @return string 僅包含中文和數字的字符串
 */
function getChinese(string $string, string $encode = "GBK"): string {
    // 確定編碼字節長度
    $codelength = match ($encode) {
        "GBK" => 2,
        "GB2312" => 3,
        "UTF-8" => 3,
        "UTF-16" => 4,
        default => 2
    };

    $tmpstr = '';
    $len = strlen($string);
    
    for ($i = 0; $i < $len; $i++) {
        $char = $string[$i];
        $ord = ord($char);
        
        // ASCII 數字直接保留
        if ($ord >= 48 && $ord <= 57) { // '0'-'9'
            $tmpstr .= $char;
            continue;
        }
        
        // 中文字符首字節特徵:高位為 1 (≥ 0xA0)
        if ($ord > 0xA0) {
            // 邊界檢查
            if ($i + $codelength <= $len) {
                $tmpstr .= substr($string, $i, $codelength);
                $i += $codelength - 1; // 跳過後續字節
            }
        }
        // 其他字符 (英文字母、標點、控制字符) 忽略
    }
    return $tmpstr;
}
?>

使用示例

<?php
// GBK 環境測試
$str_gbk = "Hello 世界 123 测试 abc";
echo getChinese($str_gbk, 'GBK'); // 輸出: "世界 123 测试"

// UTF-8 環境測試
$str_utf8 = "Hello 世界 123 测试 abc";
echo getChinese($str_utf8, 'UTF-8'); // 輸出: "世界 123 测试"

// 僅提取中文 (排除數字)
function getChineseOnly(string $string, string $encode = "UTF-8"): string {
    $result = getChinese($string, $encode);
    return preg_replace('/[0-9]/', '', $result);
}
echo getChineseOnly($str_utf8); // "世界 测试"
?>

編碼環境自動檢測增強版

<?php
function getChineseAuto(string $string): string {
    // 簡單編碼檢測邏輯
    $encode = 'UTF-8';
    if (preg_match('/[\x80-\xFF]{2,}/', $string)) {
        // 含高位字節序列,可能是 GBK/GB2312
        // 進一步檢測:GBK 中文字節範圍 0x81-0xFE
        if (preg_match('/[\x81-\xFE][\x40-\xFE]/', $string)) {
            $encode = 'GBK';
        }
    }
    return getChinese($string, $encode);
}
?>

現代 PHP 替代方案:mbstring 正則 (推薦)

<?php
// PHP 5.4+ 且啟用 mbstring 擴展
function getChineseModern(string $string): string {
    // 保留中文 (Unicode 漢字範圍) 和數字
    return preg_replace('/[^\p{Han}\d]/u', '', $string);
}

// 進階:支援日韓漢字、擴展區
function getCJKModern(string $string): string {
    return preg_replace('/[^\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}\d]/u', '', $string);
}

$str = "Hello 世界 123 测试 こんにちは 한글 🙂";
echo getChineseModern($str);  // "世界 123 测试"
echo getCJKModern($str);      // "世界 123 测试 こんにちは 한글"

方案對比

方案優點缺點適用場景
字節特徵法 (本文)無擴展依賴、可控編碼邏輯、教學價值不支援 UTF-8 變長編碼 (假設固定 3 字節)、易誤判舊項目、固定編碼環境、學習原理
mbstring 正則Unicode 標準、支援所有語言、自動處理變長編碼、性能優需 mbstring 擴展、正則語法較複雜現代 PHP 專案 (強烈推薦)
iconv 轉碼 + 字節法統一轉為固定編碼再處理雙重轉換開銷大、轉碼可能丟失字符編碼混雜的歷史數據清洗

常見陷阱

  • UTF-8 變長編碼:漢字 3 字節,但生僻字 4 字節,本文固定長度假設會截斷/誤讀
  • GBK/GB2312 混淆:字節範圍重疊,自動檢測不可靠
  • 標點符號處理:中文標點 (。,!?) 屬於不同 Unicode 類別,需顯式加入保留列表
  • Emoji/符號:4 字節 UTF-8,字節法會誤判為中文或亂碼

最佳實踐建議

  1. 新項目統一使用 UTF-8 + mbstring 正則,一行代碼解決 99% 場景
  2. 舊項目 GBK 環境可用本文函數,但需嚴格控制輸入編碼一致性
  3. 數據清洗管道:統一編碼 → 正規化 → 白名單過濾 → 業務邏輯
  4. 測試覆蓋**:包含 ASCII、中文、生僻字、Emoji、混合編碼、注入攻擊字符串

本文函數適合理解字符編碼底層原理及維護老舊 GBK 專案,現代開發請優先選擇 mbstring + Unicode 屬性正則方案。

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