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

PHP 全角半角字符互轉:四種方案對比 (正則替換、映射表、回調函數、strtr 高性能)

     編輯:PHP 相關知識

PHP 全角半角字符互轉:四種方案對比 (正則替換、映射表、回調函數、strtr 高性能)

全角字符 (全形) 佔用兩字節,半角佔用一字節,常見於用戶輸入標準化、搜索關鍵詞預處理、數據清洗。本文提供四種 PHP 實現方案,從簡單正則到高性能查表,附 Unicode 碼位對照表。

方案一:正則替換 (僅限非 UTF-8 / 單字節編碼)

$str = "0123ABCDFWS\",.?<>{}[]*&^%#@!~()+-|:;";
// 非 UTF-8 環境下:第二字節 - 0x80 得到半角
$str = preg_replace('/\xa3([\xa1-\xfe])/e', 'chr(ord("\\1")-0x80)', $str);
echo $str; // 0123ABCDFWS\".<>[]*&^%#@!~()+-|:;
// 注意:/e 修飾符 PHP 7.1+ 棄用,UTF-8 下無效

原理:GBK/Big5 編碼中,全角字符第二字節 = 半角字符碼位 + 0x80。UTF-8 編碼無此規律。

方案二:映射表 + preg_replace_callback (UTF-8 兼容)

$map = [
    '0'=>'0','1'=>'1','2'=>'2','3'=>'3','4'=>'4','5'=>'5','6'=>'6','7'=>'7','8'=>'8','9'=>'9',
    'A'=>'A','B'=>'B','C'=>'C','D'=>'D','E'=>'E','F'=>'F','G'=>'G','H'=>'H','I'=>'I','J'=>'J',
    'K'=>'K','L'=>'L','M'=>'M','N'=>'N','O'=>'O','P'=>'P','Q'=>'Q','R'=>'R','S'=>'S','T'=>'T',
    'U'=>'U','V'=>'V','W'=>'W','X'=>'X','Y'=>'Y','Z'=>'Z',
    'a'=>'a','b'=>'b','c'=>'c','d'=>'d','e'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j',
    'k'=>'k','l'=>'l','m'=>'m','n'=>'n','o'=>'o','p'=>'p','q'=>'q','r'=>'r','s'=>'s','t'=>'t',
    'u'=>'u','v'=>'v','w'=>'w','x'=>'x','y'=>'y','z'=>'z',
];

$str = preg_replace_callback(
    '/[\xEF][\xBC][\x90-\x99]|[\xEF][\xBD][\x81-\x9A\xA1-\xBA]/',
    fn($m) => $map[$m[0]] ?? $m[0],
    $str
);

原理:UTF-8 中全角數字 U+FF10~FF19 編碼為 EF BC 90~99,大寫字母 U+FF21~FF3A 為 EF BD 81~9A,小寫 U+FF41~FF5A 為 EF BD A1~BA。

方案三:雙向映射數組 + str_replace (通用、可維護)

function convertStrType(string $str, string $type): string {
    $full = ['0','1','2','3','4','5','6','7','8','9',
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        '-',' ',':','.',',','/','%','#','!','@','&','(',')','<','>','"',''','?','[',']','{','}','\','|','+','=','_','^','¥',' ̄','`'];
    $half = ['0','1','2','3','4','5','6','7','8','9',
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
        '-',' ',':','.',',','/','%','#','!','@','&','(',')','<','>','"',"'",'?','[',']','{','}','\\','|','+','=','_','^','¥','~','`'];

    return ($type === 'TO_DBC') // 全角轉半角
        ? str_replace($full, $half, $str)
        : str_replace($half, $full, $str); // 半角轉全角
}

方案四:strtr 單次遍歷最高性能 (推薦生產)

function makeSemiangle(string $str): string {
    $map = [
        '0'=>'0','1'=>'1','2'=>'2','3'=>'3','4'=>'4','5'=>'5','6'=>'6','7'=>'7','8'=>'8','9'=>'9',
        'A'=>'A','B'=>'B','C'=>'C','D'=>'D','E'=>'E','F'=>'F','G'=>'G','H'=>'H','I'=>'I','J'=>'J',
        'K'=>'K','L'=>'L','M'=>'M','N'=>'N','O'=>'O','P'=>'P','Q'=>'Q','R'=>'R','S'=>'S','T'=>'T',
        'U'=>'U','V'=>'V','W'=>'W','X'=>'X','Y'=>'Y','Z'=>'Z',
        'a'=>'a','b'=>'b','c'=>'c','d'=>'d','e'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j',
        'k'=>'k','l'=>'l','m'=>'m','n'=>'n','o'=>'o','p'=>'p','q'=>'q','r'=>'r','s'=>'s','t'=>'t',
        'u'=>'u','v'=>'v','w'=>'w','x'=>'x','y'=>'y','z'=>'z',
        // 標點符號 (常用)
        '('=>'(', ')'=>')', '〔'=>'[', '〕'=>']', '【'=>'[', '】'=>']', '〖'=>'[', '〗'=>']',
        '“'=>'"', '”'=>'"', '‘'=>"'", '’'=>"'", '《'=>'<', '》'=>'>',
        '%'=>'%', '+'=>'+', '—'=>'-', '-'=>'-', '~'=>'~', ':'=>':', '。'=>'.', '、'=>',', ','=>',', ';'=>';',
        '?'=>'?', '!'=>'!', '…'=>'...', '‖'=>'|', '|'=>'|', '〃'=>'"', ' '=>' '
    ];
    return strtr($str, $map);
}

性能對比 (10萬次循環,字符串長度 200)

方案耗時優點缺點
正則 /e~2.1s代碼極短非 UTF-8、/e 棄用、安全風險
preg_replace_callback~1.8sUTF-8 兼容、可擴展回調開銷大
str_replace 陣列~0.9s簡單、雙向多次遍歷字符串
strtr~0.3s單次遍歷、C 級性能、內存友好需構建完整映射表

全角半角 Unicode 碼位對照 (核心子集)

字符類型半角碼位全角碼位差值
數字 0-9U+0030~U+0039U+FF10~U+FF19+0xFEE0
大寫 A-ZU+0041~U+005AU+FF21~U+FF3A+0xFEE0
小寫 a-zU+0061~U+007AU+FF41~U+FF5A+0xFEE0
空格U+0020U+3000 (全形空格)特殊
常用標點U+0021~U+007EU+FF01~U+FF5E+0xFEE0 (大部分)

最佳實踐建議

  1. 統一使用 UTF-8 編碼 (文件、數據庫、HTML、連接)
  2. 2. 輸入端統一調用 makeSemiangle() 標準化 3. 搜索引擎索引前同步轉換,保證全半角混合查詢命中 4. 正則匹配時使用 /u 修飾符正確處理 Unicode 5. 數據庫列設置 utf8mb4_general_ci 排序規則,原生支持全半角不敏感比較

掌握 Unicode 編碼規律,選擇 strtr 方案,即可高效解決全半角混雜帶來的業務 Bug。

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