2020年8月14日 星期五

PHP 找出字串中不可見的字元

匯入資料時,發現資料長度,跟肉眼看到的不一樣。
此時資料中可能有不可見的字符,要看到這些字元,有個簡便的方式,
先用 json_encode() 函式處理,便可看到原本看不到的字元。
多字節的 Unicode 字元,也會轉成 \u**** 的 Unicode Code Point 格式,可看到字元在 Unicode 字元集中的編號。

情況一:
字串"test",長度4,但匯入時,長度卻為7,比看到的多了 3(使用strlen計算字算長度)。
用 json_encode() 處理後,出現 "\ufefftest",前面多了「\ufeff」
「\ufeff」:是檔案的 BOM


情況二:
字串"1234",長度4,但匯入時,長度卻為10,比看到的多了 6(使用strlen計算字算長度)。
用 json_encode() 處理後,出現 "\u202d1234\u202c",前面多了「\u202d」,後面多了「\u202c」
網上查到以下兩種情況可能會發生
1.在 iphone 通訊錄,複製電話號碼(我沒iphone,就沒試了)
 參考:iOS通讯录复制的手机号码字符串多了奇怪的unicode码\\u0000202d-\\u0000202c_lnking1992的专栏-CSDN博客_通讯录号码复制有特殊字符
2.excel 中複製欄位資料(我測試沒試出來)
參考:记一次编码导致的问题:\\u202d和\\u202c_fan3394565的博客-CSDN博客_\\u202c

前後不可見的字元分別是,LRO、PDF
「\u202e」:RLO,Unicode控制字符,開始從右到左的文字
「\u202d」:LRO,Unicode控制字符,開始從左到右的文字
「\u202c」:PDF,Unicode控制字符,結束上一次定義


[將不可見的特殊字元去除]
因為都剛好在字串前後,我就直接只用 trim() 處理
trim($str, " \t\n\r\0\x0B\u{feff}\u{202d}\u{202c}");
//" \t\n\r\0\x0B"為 trim 預設就會去除的特殊字元

BOM「\ufeff用16進位表示為\xef\xbb\xbf
也可寫成
trim($str, " \t\n\r\0\x0B\xef\xbb\xbf\u{202d}\u{202c}");


其他:
\u{****}寫法,PHP7才支援,也可用 json_decode 將 Unicode Code Point  轉回。
var_dump(json_decode('"\u202d"'));
var_dump(json_decode('"\u9999"'));


參考:
关于Unicode控制字符RLO,LRO,PDF 的坑 - scgaopan的个人空间 - OSCHINA
Unicode codepoint 轉譯語法
碼位 - 維基百科,自由的百科全書
php - UTF-8 to Unicode Code Points - Stack Overflow
PHP - 使用PHP將Unicode字符轉換為“\ uxxxx”格式 | php Tutorial




1 則留言:

  1. 感謝筆者的用心分享
    非常實用且值得筆記的資訊!!

    回覆刪除