針對特定編碼環境下從混合字符串中提取中文字符的需求,本文提供一個基於字節高位特徵判斷的函數 getChinese(),支援 GBK/GB2312/UTF-8/UTF-16 多種編碼,同時保留數字字符。
<?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
// 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 轉碼 + 字節法 | 統一轉為固定編碼再處理 | 雙重轉換開銷大、轉碼可能丟失字符 | 編碼混雜的歷史數據清洗 |
本文函數適合理解字符編碼底層原理及維護老舊 GBK 專案,現代開發請優先選擇 mbstring + Unicode 屬性正則方案。