<<vim中編輯不同編碼的檔案時需要注意的一些地方>>
Tags: vim, linux-tool, edit
此文講解的是vim編輯多位元組編碼文檔(中文)所要瞭解的一些基礎知識, 注意其沒有涉及
gvim, 純指字元終端下的vim.
1. vim編碼方面的基礎知識:
1.1 3個變數:
encoding 該選項使用於緩衝的文本(你正在編輯的檔案), 寄存器, Vim 指令檔等
等. 你可以把 'encoding' 選項當作是對 Vim 內部運行機制的設定.
fileencoding 該選項是vim寫入檔案時採用的編碼類別型.
termencoding 該選項代表輸出到客戶終端(Term)所採用的編碼類別型(只有把其設定為與
終端編碼類別型相同才可能正常顯示字元!).
1.2 此3個變數的預設值:
encoding 與系統當前locale相同, 所以編輯檔案的時候要考慮當前locale, 否則要
設定的東西就比較多了.
fileencoding vim開啟檔案時自動辨認其編碼, fileencoding就為辨認的值. 為空白則保
存檔案時採用encoding的編碼, 如果沒有修改encoding, 那值就是系統當
前locale了.
termencoding 預設空值, 也就是輸出到終端不進行編碼轉換.
由此可見, 編輯不同編碼檔案需要注意的地方不僅僅是這3個變數, 還有系統當前locale
和,檔案本身編碼以及自動編碼識別,客戶運行vim的終端所使用的編碼類別型3個關鍵點, 這
3個關鍵點影響著3個變數的設定.
如果有人問: 為什麼我用vim開啟中文文檔的時候出現亂碼?
答案是不確定的, 原因上面已經講了, 不搞清楚這3個關鍵點和這3個變數的設定值, 出現
亂碼是正常的, 倒是不出現亂碼那反倒是湊巧的.
1.3 常見情況下這三個關鍵字的值以及在這種情況下這3個變數的值
1.3.1 locale
目前大部分Linux系統已經將utf-8作為預設locale了, 不過也有可能不是, 例如有些系統
使用中文locale zh_CN.GB18030. 在locale為utf-8的情況下, 啟動vim後encoding將會設
置為utf-8, 這是相容性最好的方式, 因為內部 處理使用utf-8的話, 無論外部儲存編碼
為何都可以進行無缺損轉換. (locale決定了vim內部處理資料的編碼, 也就是encoding).
1.3.2 檔案的編碼以及自動編碼識別
這方面牽扯到各種編碼的規則, 就不一一細講了. 但需要明白的是, 檔案編碼類別型並不是
儲存在檔案內的, 也就是說沒有任何 描述性的欄位來記錄文檔是何種編碼類別型的. 因此
我們在編輯文檔的時候, 要麼必須知道這文檔儲存時是以什麼編碼儲存的, 要麼通過另外
的一些手段來斷定編碼類別 型, 這另外的手段, 就是通過某些編碼的碼錶特徵來斷定, 例
如每個字元佔用的位元組數, 每個字元的ascii值是否都大於某個欄位來斷定這個檔案屬於
何種編 碼. 這種方式vim也使用了, 這就是vim的自動編碼識別機制了. 但這種機制由於
編碼各式各樣, 不可能每種編碼都有顯著的特徵來辨別, 所以是不可能 100%準確的. 對
於我們GB2312編碼, 由於其中文是使用了2個acsii值高於127的字元組成漢字字元的, 因
此不可能把gb2312編碼的檔案與 latin1編碼區分開來, 因此自動識別編碼的機制對於
gb2312是不成功的, 它只會將檔案辨識為latin1編碼. 此問題同樣出現在gbk, big5 上等
; 因此我們在編輯此類文檔時, 需要手工設定encoding和fileencoding. 如果文檔編碼為
utf-8時, 一般vim都能自動識別正確的 編碼.
1.3.3 客戶運行vim的終端所使用的編碼類別型
同第二條一樣, 這也是一個比較難以斷定的關鍵點. 第二個關鍵點決定著從檔案讀取內容
和寫入內容到檔案 時使用的編碼, 而此關鍵點則決定vim輸出內容到終端時使用的編碼,
如果此編碼類別型和終端認為它收到的資料的編碼類別型不同, 則又會產生亂碼問題. 在
linux本地X環境下, 一般終端都認為其接收的資料的編碼類別型和系統locale類型相符, 因
此不需關心此方面是否存在問題. 但如果牽涉到遠程終端, 例 如ssh登入伺服器, 則問題
就有可能出現了. 例如從1台locale為GB2310的系統(稱作客戶機)ssh到locale為utf-8的
系統(稱作服 務器)並開啟vim編輯文檔, 在不加任何改動的情況下,伺服器返回的資料為
utf-8的, 但客戶機認為伺服器返回的資料是gb2312的, 按照gb2312來解釋資料, 則肯定
就是亂碼了, 這時就需要設定termencoding為gb2312來解決這個問題. 此問題更多出現在
我們的 windows desktop機遠程ssh登入伺服器的情況下, 這裡牽扯到不同系統的編碼轉
換問題. 所以又與windows本身以及ssh用戶端有很大相關性. 在 windows下存在兩種編碼
類型的軟體, 一種是本身就為unicode編碼方式編寫的軟體, 一種是ansi軟體, 也就是程
序處理資料直接採用位元組流, 不 關心編碼. 前一種程式可以在任何語言的windows上正確
顯示多國語言, 而後一種則編寫在何種語言的系統上則只能在何種語言的系統上顯示正確
的文字. 對 於這兩種類型的程式, 我們需要區別對待. 以ssh用戶端為例, 我們使用的
putty是unicode軟體, 而secure CRT則是ansi 軟體. 對於前者, 我們要正確處理中文,
只要保證vim輸出到終端的編碼為utf-8即可, 就是termencoding=utf-8. 但對於後者, 一
方面 我們要確認我們的windows系統預設字碼頁為cp936(中文windows預設值), 另一方面
要確認vim設定的termencoding= cp936.
2. 看看處理中文文檔最典型的幾種情況和設定方式:
1) 系統locale是utf-8(很多linux系統預設的locale形式), 編輯的文檔是GB2312或GBK形
式的(Windows記事本 預設儲存形式, 大部分編輯器也預設儲存為這個形式, 所以最
常見), 終端類型utf-8(也就是假定用戶端是putty類的unicode軟體)
則vim開啟文檔後, encoding=utf-8(locale決定的), fileencoding=latin1(自動編
碼判斷機制不準導致的), termencoding=空(預設無需轉換term編碼), 顯示檔案為亂
碼.
solution:
1. 首先要修正fileencoding為cp936或者euc-cn(二者一樣的, 只不過叫法不同),
注意修正的方法不是:set fileencoding=cp936, 這隻是將檔案儲存為cp936, 正
確的方法是重新以cp936的編碼方式負載檔案為:edit ++enc=cp936, 可以簡寫為
:e ++enc=cp936.
2. 臨時改變vim啟動並執行locale環境, 方法是以LANG=zh_CN vim abc.txt的方式來啟
動vim, 則此時encoding=euc-cn(locale決定的), fileencoding=空(此locale下
檔案編碼自動判別功能不啟用, 所以fileencoding為檔案本身編碼方式不變, 也
就是euc-cn), termencoding=空(預設值, 為空白則等 於encoding)此時還是亂碼
的, 因為我們的ssh終端認為接受的資料為utf-8, 但vim發送資料為euc-cn, 所
以還是不對. 此時再用命令: set termencoding=utf-8將終端資料輸出為utf-8,
則顯示正常.
2) 情況與1基本相同, 只是使用的ssh軟體為secure CRT類ansi類軟體. vim開啟文檔後
, encoding=utf-8(locale決定的), fileencoding=latin1(自動編碼判斷機制不準導
致的), termencoding=空(預設無需轉換term編碼), 顯示檔案為亂碼.
solution:
1. 首先要保證運行secure CRT的windows機器的預設字碼頁為CP936, 這一點中文
windows已經是預設設定了. 其他的與上面方案1相同, 只是要增加一步, :set
termencoding=cp936
2. 與上面方案2類似, 不過最後一步修改termencoding省略即可, 在此情況下需要
的修改最少, 只要以locale為zh_CN開 啟vim, 則encoding=euc-cn,
fileencoding和termencoding都為空白即為encoding的值, 是最理想的一種情 況.
可見理解這3個關鍵點和3個參數的意義, 對於編碼問題有很大助力, 以後就可以隨心所欲
的處理文檔了, 同時不僅僅是應用於vim, 在其他需要編碼轉換的環境裡, 都可以應用類
似的思路來處理問題解決問題.
最後推薦一款功能強大的windows下的ssh用戶端--xshell, 它具有類似secure CRT一樣的
多tab 的ssh視窗的能力, 但最為方便的是這款工具還有改變Term編碼的功能, 這樣我們
就可以不用頻繁調整termencoding, 只需在ssh軟體裡切換 編碼即可, 這是我用過的最為
方便的ssh工具. 它是商業軟體, 但非註冊使用者使用沒有任何限制, 只是30天試用期超出
後會每次啟動都提示註冊, 對於功能沒有 絲毫影響.