en_US.utf8 和 en_US.UTF-8 有區別嗎?
伺服器資訊(已刪除 DNS 和 IP):
cat /proc/version && uname -a && java -version Linux version 2.6.16.33-xenU (*************) (gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)) #2 SMP Wed Aug 15 17:27:36 SAST 2007 Linux ************* *************-xenU #2 SMP Wed Aug 15 17:27:36 SAST 2007 x86_64 x86_64 x86_64 GNU/Linux java version "1.6.0_14" Java(TM) SE Runtime Environment (build 1.6.0_14-b08) Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
我有一些從 Excel 文件中讀取並進行字元串比較的 PHP 程式碼。由於似乎是語言環境問題,它在伺服器上失敗了。但是,在我的本地機器(OSX 10.8.5 Mountain Lion)上,它可以工作!
在我的本地機器上,語言環境是 en_US.UTF-8。在伺服器上,語言環境是 POSIX 但我將其更改為 en_US.utf8 因為當我查看locale -a時沒有 en_US.UTF-8 (有趣的是,伺服器上的語言環境列表都是小寫的,但在我的 Mac 上它們都是大寫的,這就是這個問題的來源)。
兩者之間是否存在可能影響字元串比較的差異?
另外,根據這篇 SF 文章,我執行了locale -v -a。在伺服器上, en-US.utf8 使用 UTF-8 程式碼集(我假設這與我通常所說的字元集相同?)。但是,在我的本地機器上,我似乎無法執行locale -v -a命令,儘管locale和locale -a工作正常。
TL; 博士:
據我所知,其中的程式碼頁/字元集並未得到官方
.utf8
認可。en_US.utf8
沒有 IANAutf8
字元集名稱。utf8
可能是由glibc
- 見最終標題生成的。IANA 字元集名稱是
UTF-8
.
- 連字元很重要
- 大小寫敏感**_**
因此,這些都是有效的:
en_US.utf-8
en_US.UTF-8
en_US.uTf-8
還有一個!區分大小寫!名稱的別名,即:。
UTF-8``csUTF8
因此,這也是有效的:
en_US.csUTF8
但我從未在野外見過這種情況。
細節,有章節和經文
UTF-8
是有效的 IANA 字元集名稱,而utf8
不是。它甚至不是一個有效的別名。POSIX.1-2017,第8.2 節國際化變數說:
如果語言環境值具有以下形式:
language[_territory][.codeset]
它指的是實現提供的語言環境,其中語言、區域和程式碼集的設置是實現定義的。
這裡有問題的
[.codeset]
部分是 POSIX 沒有定義的部分,但 IANA 定義了。對於 RFC2978: 定義的字元集
UTF-8, a transformation format of ISO 10646
, IANA Character Sets將名稱列為:
UTF-8
頂部的註釋說:
這些是可以在 Internet 中使用的字元集的正式名稱,並且可以在 Internet 文件中引用。
提供了一個別名
csUTF8
,關於RFC2978 IANA 字元集註冊程序,第 2.3 節說:所有其他名稱都被視為主名稱的別名,使用主名稱優於使用任何別名。
IANA 字元集還說:
“cs”代表字元集,用於需要小寫首字母但希望在其後使用混合大小寫且不能包含任何特殊字元的應用程序,例如下劃線(“_”)和破折號(“-”)。
在
cs
別名中,大小寫很重要(而名稱在上面定義為不區分大小寫)。給定別名
csUTF8
,en_US.csUTF8
也是有效的,但我從未在野外見過這種格式。雖然大小寫在aliases中很重要,但關於names,IANA Character Sets說:
字元集名稱最多可包含 40 個字元,取自 US-ASCII 的可列印字元。但是,大小寫字母的使用沒有區別。
因此,雖然
en_US.utf-8
是有效的(列出的小寫版本UTF-8
),en_US.utf8
但它不引用 IANA 字元集,因為它刪除了-
.如果不是 IANA,它
utf8
可能來自哪裡?glibc
_nl_normalize_codeset()
執行以下操作:
- 只傳遞字元或數字(再見連字元)
- 將字元轉換為小寫
for (cnt = 0; cnt < name_len; ++cnt) if (__isalpha_l ((unsigned char) codeset[cnt], locale)) *wp++ = __tolower_l ((unsigned char) codeset[cnt], locale); else if (__isdigit_l ((unsigned char) codeset[cnt], locale)) *wp++ = codeset[cnt];