[轉貼]將 locale 從 zh_CN.GB2312 轉到 zh_CN.UTF-8 的一些問題

一直想把自己的 Linux box 從 zh_CN.GB2312 的 locale 設置遷移到 zh_CN.UTF-8 上去,無奈之前的大量的實驗中用到的文件都是 GB2312 編碼的,所以,這個遷移直到最近因爲要在一個工具上添加 UTF-8 編碼的中文支持才得以完成。以下是我在這個遷移的過程碰到的一些和中文相關的問題以及我個人的解決方法,列此一來備忘,二來希望能給有相同需求的朋友做個 參考。

提醒:以下提及的工具中的大部分會對你的原始文件進行”寫”操作,也就是說, 轉換出來的結果可能會產生錯誤或者偏差。如果你不是一個有經驗的 Linux 用戶,請在做這些操作的時候,注意先做好備份。並強烈建議你在使用某一個工具之 前,先仔細閱讀該工具的 manual。(”man program-name”)

0、支持 Unicode 的 Terminal 工具

我選擇 Terminal 工具的原則是:輕量(佔用系統資源小)且強大。基於之前我的一個簡單評測,我現在用的 Terminal 工具是 rxvt-unicodescreen。xterm 對 unicode 的支持可能是最差的,除此之外,mlterm、GNOME-terminal 等工具雖然都能很好的支持 unicode,不過 mlterm 的 multi tab 功能在我更習慣於使用”screen”來做 multi tab 這點上顯得有點多餘;而 gnome-terminal 則太過於耗資源。rxvt-unicode 則剛好合我的胃口,尤其是它的 server+client 的模式可以在開啓多個 Terminal 的時候節省大量的系統資源。:)

1、文件內容的編碼檢測及轉換

文件內容的編碼轉換可以結合 2 個工具來完成。

a.如果你不知道你所要轉換的文件的編碼格式,你可以通過 enca 這個工具來檢測編碼。舉例如下:

joseph@PeT43: ~ > enca foo.txt

Universal transformation format 8 bits; UTF-8

b.如果你事先已經知道了文件的編碼或者通過檢測知道了文件的編碼,可以通過 GNU 的 iconv 來進行編碼轉換。以下是一個例子用來把文件的編碼從 GB2312 轉換成 UTF-8:

joseph@PeT43: ~ > iconv -f gb2312 -t utf-8 foo.txt > foot.txt.utf-8

提醒:iconv 的輸出默認是直接輸出到標準輸出(standard output),通常就是你的屏幕上。所以,你需要使用”>”的重定向符號來把輸出轉存到一個”新”的文件裏面去。切不可在”>”後面使用你 的原始的輸入文件名作爲輸出文件名,因爲”>”操作,會首先將其後面的文件清空,然後再運行 “>”前面的操作。也就是說,除了原始的輸入文件被清空之外,你什麼也得不到。這是很多 Linux 新用戶經常會犯的一個”致命”錯誤。特此提醒。

2、文件名的編碼轉換

上述的 2 個工具只能對文件的內容進行編碼的檢測和轉換,如果需要對文件名進行編碼轉換,則需要 convmv 來完成。convmv 的用法大致和 iconv 相似,以下是一個例子用來將”music”這個目錄下的所有以 GB2312 編碼的文件名的文件和子目錄下的文件,轉換成以 UTF-8 編碼的文件名:

joseph@PeT43: ~ > convmv -f gb2312 -t utf-8 -notest -r music

請注意這裏的”-notest”選項:如果不提供這個選項,該命令只會做一個轉換的測試,並不會真正的轉換。因爲這個命令有一定的”破壞性”,所 以,當你用這個程序的時候,最好是先不用”-notest”這個選項來做一遍測試,根據程序運行輸出的信息來確定是否有個別的文件需要手動進行調整。

3、MP3 的 ID3 tag 編碼轉換

一個比較擾人的問題是,MP3 裏面的 ID3(v1/v2) Tag 信息不能象普通的文本文件那樣來用 iconv 進行編碼轉換。好在這個問題 Feng Zhou 也碰到了,他寫了一個 java 的程序 ID3iconv 來處理這些 MP3 文件的 ID tag 編碼轉換。

略有不足的是,這個程序沒有提供一個類似於上面提及的 convmv 的”-r”(recursive)的選項可以來對某一個目錄下的所有文件和子目錄下的文件進行遞歸的處理。當然,我們可以用萬能的“find”命令來彌補 這個缺陷,以下是一個例子,用來對”music” 目錄裏面的所有 mp3 文件(含子目錄下的文件)進行 ID3 tag 的轉換:

joseph@PeT43: ~ > find . -name '*.mp3' -exec java -jar /usr/local/bin/id3iconv-0.2.1.jar -e gb2312 '{}' ;

這個命令利用到了”find”命令的”-exec”選項來對所有找到的文件進行指定的操作,這裏“指定的操作”就是對該文件調用 id3iconv 這個 java 的程序來進行 ID3 tag 的編碼格式轉換。詳情請參考 find 的 manual (man find)。

4、在 rxvt-unicode terminal 中實時改變 locale 設置

我所碰到的一個比較擾人的問題是,雖然現在日常的操作多數是在 UTF-8 的 locale 下進行的,但是很多時候我又需要一個基於 GB2312 的 rxvt- unicode 來跑原來的一些實驗。簡單的在一個現有的 rxvt-unicode session 下通過”export LC_CTYPE=zh_CN.GB2312″其實並不奏效。因爲那只是告訴你的 bash 程序,此後的 locale 變成了 zh_CN.GB2312,而 rxvt-unicode 程序本身卻依然工作在它啓動時候的 zh_CN.UTF-8 的 locale 下。所以,即使改變了 bash 的 locale 設置,但如果在該 rxvt-unicode 中用 cat 或者 more 這樣的命令來查看一個以 zh_CN.GB2312 的文件,依然看到是一堆亂碼。

在這種情況下,一種不需要重新設置 X 系統的 locale,實時修改運行狀態下的 rxvt-unicode 本身的 locale 設置的解決方案是使用 rxvt-unicode 內置的”escape sequence”來實現。

如下的 2 個命令組合,先更改 bash 的 locale 設置,然後通過”escape sequence”通知 rxvt-unicode 程序,現在這個 session 的 locale 設置已經被改成了 zh_CN.GB2312:

joseph@PeT43: ~ > export LC_CTYPE=zh_CN.gb2312; printf "33]701;$LC_CTYPE?07"

這樣,你就實時的得到一個 zh_CN.GB2312 的環境,可以對 zh_CN.GB2312 的文件進行正確的顯式和操作了。

如果需要轉回到 zh_CN.UTF-8 的模式,則可以通過如下的命令來實現:

joseph@PeT43: ~ > export LC_CTYPE=zh_CN.utf8; printf "33]701;$LC_CTYPE?07"

當然,每次敲這麼長的命令挺煩人的,我用的方法是把上面的這 2 個命令集合分別存成 .bash.gb 和 .bash.utf-8 兩個文件,放到我的 home 目錄。

如果我需要實時得到一個 GB2312 的 rxvt-unicode session,我就運行:

joseph@PeT43: somewhere > source ~/.bash.gb

如果我需要實時得到一個 UTF-8 的 rxvt-unicode session,我就運行:

joseph@PeT43: somewhere > source ~/.bash.utf-8

這樣就省卻了很多敲鍵盤或者 copy/paste 的時間。:)

這個方法是從 rxvt-unicodeFAQ 中學來的。這個”701″的 escape sequence 是 rxvt-unicode 對 xterm 的 escape sequence 的擴展,只在 rxvt-unicode 中有效。

[在 GNOME Terminal 裏面可以通過菜單裏面的”Terminal|Set Character Encoding”來實時更改 locale。]

5、VIM 配置文件的更新

我是一個 VIMmer,以下是一些我在 UTF-8 環境下的 vim 的配置:

set encoding=utf-8 " set default encoding as UTF-8

set fileencodings=ucs-bom,utf-8,cp936,latin1 " fileconding detection order

set termencoding=utf-8 " support Chinese display in rxvt-unicode

6、Misc

以下是一些小技巧,簡單羅列在下面。

a. 在做編碼轉換的時候,如果你的源格式設定爲 GB2312 的話,而且在轉換成 UTF-8 的時候,發現程序會報“illegal input sequence at position xxxx”的錯誤。這是由於你之前的做的假定有問題。GB2312 是國標裏面一個最小也是最早的中文編碼標準。其中,只涵蓋了 6,763 個漢字。所以你需要轉換的文件的原始的格式可能並不是 GB2312 編碼。這個時候,你可以用 GB18030 做爲源格式來進行轉換。GB18030 是最新的國家標準,包含了 27,564 個漢字,而且向下兼容 GB2312 和 GBK。

b.另外,支持 Unicode 且 Free 的中文字庫我推薦使用”文泉驛“。這好像也是目前爲止,唯一的一個以支持 Unicode 爲出發點的 Free 的中文字庫。

7、一些有用的參考:

a. Markus Kuhn 的”UTF-8 and Unicode FAQ for Unix/Linux“。最爲詳盡的 FAQ。

b. Unicode Home Page。Unicode 的官方網站。

c. A Quick Primer On Unicode and Software Internationalization Under Linux and UNIXEd Trager 提供的一個關於如何在 Linux 下使用 Unicode 的 tutorial,涵蓋了一些我沒有提及的內容。推薦閱讀。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章