1. 程式人生 > >Gnome Terminal,Xshell等終端模擬器中執行命令出現亂碼問題解決

Gnome Terminal,Xshell等終端模擬器中執行命令出現亂碼問題解決

一、前言

Xshell跟Gnome Terminal相比,兩者都是終端模擬器(在Xshell中也可以執行簡單的內建命令,如“cd”,“ls”等),地位相同。

二、原理分析

涉及到亂碼,那麼需要了解編碼解碼過程。在終端模擬器中執行命令,通訊過程示意圖如圖1所示。

圖1
這裡寫圖片描述

在以上通訊過程中,在“命令執行單元”處發生了一系列的編碼解碼過程,在“終端模擬器”處也發生了一系列的編碼解碼過程,此外,我們常常建立SSH連線,從而建立一個遠端Shell會話,在該情景中,通訊過程示意圖如圖2所示,由圖2可知,在該情景中,跟原來的通訊過程相比,只不過“命令執行單元”處與“終端模擬器”處之間的通訊資料經過SSH安全通道而已,一般並不影響整體的編碼解碼過程。

圖2
這裡寫圖片描述

“命令執行單元”處執行命令過程中會發生一系列的編碼解碼過程,不同命令具有不同實現,因而不同命令執行過程中發生的編碼解碼過程也不盡相同(以下這些連結中的內容可作為該結論的證據:《使用vi和less檢視文字出現中文亂碼,使用cat正常》《檢視日誌檔案more正常,用less查看出現亂碼》)。另外,很多命令在執行過程中會去讀取locale系列環境變數(比如“LANG”,“LANGUAGE”,“LC_ALL”,“LC_CTYPE”等)的配置值用於編碼解碼過程。
比如“uniq”命令會去使用“LC_COLLATE”等環境變數的配置值,“grep”命令會去使用“LC_ALL”等環境變數的配置值,“vim”命令會去使用“LC_CTYPE”等環境變數的配置值。

“終端模擬器”處執行命令過程中也會發生一系列的編碼解碼過程,主要有3方面內容:
1、配置終端模擬器使用的編碼方案,對於Gnome Terminal,在圖3所示位置進行配置,對於Xshell,在圖4所示位置進行配置,對於Xftp,在圖5所示位置進行配置
2、執行命令時,使用終端模擬器配置的編碼方案,對原命令字串進行編碼,將得到的位元組流傳遞給“命令執行單元”
3、展現命令執行結果時,獲取位元組流形式的命令執行結果,使用終端模擬器配置的編碼方案,對其進行解碼,得到字串形式的命令執行結果

圖3
這裡寫圖片描述

圖4
這裡寫圖片描述

圖5
這裡寫圖片描述

三、實驗

3.1、ls命令

3.1.1、實驗1

現有一個名為“你好嗎.txt”的檔案,相應於該檔名的儲存內容儲存的是使用“UTF-8”編碼方案編碼得到的位元組流。
設定不同的locale系列環境變數配置值和終端模擬器編碼方案,得到不同的“ls命令”執行結果,具體如表1。

表1

locale系列環境變數配置值 終端模擬器(實驗了Gnome Terminal和Xshell)編碼方案 ls命令執行結果截圖
zh_CN.utf8 UTF-8 這裡寫圖片描述
zh_CN.gbk UTF-8 這裡寫圖片描述
zh_CN.utf8 GBK 這裡寫圖片描述
zh_CN.gbk GBK 這裡寫圖片描述

3.1.2、實驗2

現有一個名為“你好嗎.txt”的檔案,相應於該檔名的儲存內容儲存的是使用“GBK”編碼方案編碼得到的位元組流。
設定不同的locale系列環境變數配置值和終端模擬器編碼方案,得到不同的“ls命令”執行結果,具體如表2。

表2

locale系列環境變數配置值 終端模擬器(實驗了Gnome Terminal和Xshell)編碼方案 ls命令執行結果截圖
zh_CN.utf8 UTF-8 這裡寫圖片描述
zh_CN.gbk UTF-8 這裡寫圖片描述
zh_CN.utf8 GBK 這裡寫圖片描述
zh_CN.gbk GBK 這裡寫圖片描述

3.2、vim命令

3.2.1、實驗1

現有一個名為“a.txt”的檔案,儲存有內容“你好嗎?”,使用的編碼格式為“UTF-8”。
設定不同的locale系列環境變數配置值和終端模擬器編碼方案,得到不同的“vim a.txt”執行結果,具體如表3。

表3

locale系列環境變數配置值(跟“3.1、ls命令”一樣,也是將locale系列中的所有環境變數的配置值設為同一個值) 終端模擬器(實驗了Gnome Terminal和Xshell)編碼方案 “vim a.txt”命令執行結果截圖 VIM環境中執行“:e ++enc=utf8”結果截圖
zh_CN.utf8 UTF-8 這裡寫圖片描述 這裡寫圖片描述
zh_CN.gbk UTF-8 這裡寫圖片描述 這裡寫圖片描述
zh_CN.utf8 GBK 這裡寫圖片描述 這裡寫圖片描述
zh_CN.gbk GBK 這裡寫圖片描述 這裡寫圖片描述

3.2.2、實驗2

現有一個名為“a.txt”的檔案,儲存有內容“你好嗎?”,使用的編碼格式為“GBK”。
設定不同的locale系列環境變數配置值和終端模擬器編碼方案,得到不同的“vim a.txt”執行結果,具體如表4。

表4

locale系列環境變數配置值(跟“3.1、ls命令”一樣,也是將locale系列中的所有環境變數的配置值設為同一個值) 終端模擬器(實驗了Gnome Terminal和Xshell)編碼方案 “vim a.txt”命令執行結果截圖 VIM環境中執行“:e ++enc=gbk”結果截圖
zh_CN.utf8 UTF-8 這裡寫圖片描述 這裡寫圖片描述
zh_CN.gbk UTF-8 這裡寫圖片描述 這裡寫圖片描述
zh_CN.utf8 GBK 這裡寫圖片描述 這裡寫圖片描述
zh_CN.gbk GBK 這裡寫圖片描述 這裡寫圖片描述

四、其他

4.1、locale系列環境變數

在以上實驗中,locale系列中的所有環境變數的配置值都被設為“zh_CN.gbk”或者“zh_CN.utf8”,其實“ls命令實現”或者“vim命令實現”只需要讀取locale系列中特定的部分的環境變數的配置值即可,locale系列中其他的環境變數的配置值並不會影響“ls命令”或者“vim命令”的執行。只不過我們並不知道上述提及的“locale系列中特定的部分的環境變數”是哪些,故而為了簡單起見,將locale系列中的所有環境變數的配置值都設為“zh_CN.gbk”或者“zh_CN.utf8”。

4.2、推測vim命令讀取檔案內容發生的主要的編碼解碼過程

由“3.2、vim命令”中的實驗可推知,使用vim命令讀取檔案內容中發生的主要的編碼解碼過程如下:讀取檔案內容的位元組流,使用locale系列環境變數指定的編碼方案(也可以通過“:e ++enc=?”命令自己指定要使用的編碼方案)對位元組流進行解碼得到檔案內容的字元流,再使用locale系列環境變數指定的編碼方案對獲得的字元流進行編碼得到位元組流,將前述編碼得到的位元組流傳遞給終端模擬器。
因而,只要locale系列環境變數指定的編碼方案跟終端模擬器使用的編碼方案一致,那麼直接可以得到檔案內容的非亂碼展現或者通過“:e ++enc=?”命令得到檔案內容的非亂碼展現。

4.3、實驗中用到的兩個指令碼

指令碼1:

#!/bin/bash 

cd /home/dsl/tmp/shell

export LC_ALL=$1
export LANG=$1
export LANGUAGE=$1

locale

echo "---------"
echo "---------"
echo "---------"

ls

指令碼2:

#!/bin/bash 

cd /home/dsl/tmp/shell

export LC_ALL=$1
export LANG=$1
export LANGUAGE=$1

locale

echo "---------"
echo "---------"
echo "---------"

vim a.txt