| 字符類型 | Unicode 範圍(十進制) | Unicode 範圍(十六進制) |
|---|---|---|
| 全角字符 | 65281 ~ 65374 | 0xFF01 ~ 0xFF5E |
| 半角字符 | 33 ~ 126 | 0x21 ~ 0x7E |
| 全角空格 | 12288 | 0x3000 |
| 半角空格 | 32 | 0x20 |
規律:除空格外,全角/半角字符 Unicode 碼位差值固定為 0xFEE0 (65248)。全角 = 半角 + 0xFEE0。
/**
* Unicode 碼位轉 UTF-8 字符
* @param int $unicode
* @return string UTF-8 字符
*/
function unicode2Char($unicode) {
if ($unicode < 128) return chr($unicode);
if ($unicode < 2048) return chr(($unicode >> 6) + 192) . chr(($unicode & 63) + 128);
if ($unicode < 65536) return chr(($unicode >> 12) + 224) . chr((($unicode >> 6) & 63) + 128) . chr(($unicode & 63) + 128);
if ($unicode < 2097152) return chr(($unicode >> 18) + 240) . chr((($unicode >> 12) & 63) + 128) . chr((($unicode >> 6) & 63) + 128) . chr(($unicode & 63) + 128);
return false;
}
/**
* UTF-8 字符轉 Unicode 碼位
* @param string $char 單個 UTF-8 字符
* @return int|false
*/
function char2Unicode($char) {
$len = strlen($char);
if ($len == 1) return ord($char);
if ($len == 2) return (ord($char[1]) & 63) | ((ord($char[0]) & 31) << 6);
if ($len == 3) return (ord($char[2]) & 63) | ((ord($char[1]) & 63) << 6) | ((ord($char[0]) & 15) << 12);
if ($len == 4) return (ord($char[3]) & 63) | ((ord($char[2]) & 63) << 6) | ((ord($char[1]) & 63) << 12) | ((ord($char[0]) & 7) << 18);
trigger_error('Invalid UTF-8 character', E_USER_WARNING);
return false;
}
function sbc2Dbc($str) {
return preg_replace_callback(
'/[\x{3000}\x{FF01}-\x{FF5E}]/u',
function ($matches) {
$unicode = char2Unicode($matches[0]);
if ($unicode === 0x3000) return ' '; // 全角空格
$code = $unicode - 0xFEE0;
return ($code > 255) ? unicode2Char($code) : chr($code);
},
$str
);
}
function dbc2Sbc($str) {
return preg_replace_callback(
'/[\x{0020}\x{0021}-\x{007E}]/u',
function ($matches) {
$unicode = char2Unicode($matches[0]);
if ($unicode === 0x0020) return unicode2Char(0x3000); // 半角空格
$code = $unicode + 0xFEE0;
return ($code > 255) ? unicode2Char($code) : chr($code);
},
$str
);
}
注意:使用 preg_replace_callback 替代已棄用的 /e 修飾符,支援 PHP 7+。
$a = 'abc12 345'; // 半角
$sbc = dbc2Sbc($a); // → 'abc12 345'
$dbc = sbc2Dbc($sbc); // → 'abc12 345'
var_dump($a, $sbc, $dbc);
/*
string(9) "abc12 345"
string(27) "abc12 345"
string(9) "abc12 345"
*/
// 需啟用 mbstring 擴展
mb_convert_kana($str, 'KV', 'UTF-8'); // 全角轉半角
mb_convert_kana($str, 'kv', 'UTF-8'); // 半角轉全角
// 選項:K=片假名轉平假名, V=濁音合併, k=平假名轉片假名, v=濁音展開
mb_convert_kana 專為日文設計,但對中文全半角轉換同樣有效,性能更優、邊界情況處理更完善。