现象
当我们用vi打开文件的时候,会出现乱码,如下:
1.查看当前系统的编码环境
2.查看当前终端工具编码显示
3.查看脚本文件编码显示
4.查看VI可支持的编码
当前默认采用的编码
:set fileencoding
可以看到,当前的是Latin编码,所以不管我们在终端如何设置编码修改,使用vi都会是乱码
vi /etc/virc 查看相关脚本
这段Vi脚本的作用是:当Vi的当前语言设置(v:lang
)表明环境支持UTF-8编码(无论大小写)时,将fileencodings
选项设置为ucs-bom,utf-8,latin1
。
v:lang
来源有三个地方:
1.当前 shell 环境中的 LANG 或 LC_ALL 环境变量。
2.用户在 Vim 配置文件(如 ~/.vimrc)中通过 :set lang 或 :language 命令的设置。
3.Vim 启动时通过 -L 或 --lang 参数指定的语言环境。
解决方式一
1.由上可知,系统默认编码和文件编码以及终端显示都不一样,所以我们只需要把文件系统编码设置成gb2312即可,如下:
# 1.编写一个locale.sh
vi locale.sh
LC_ALL="zh_CN.GB2312"
LANG="zh_CN.GB2312"
export LC_ALL
export LANG
# 2.若要使脚本中的环境变量更改影响当前Shell会话,应在当前Shell中使用 `source` 或 `.` 命令执行脚本
source locale.sh
2.再次打开,即正常(注意:只对当前会话有效)
解决方式二
我们可以不用改变系统的默认编码方式,而是改变终端和vi查看编码的方式
1.终端改用utf8
2.vi增加gbk方式显示
:e ++enc=gb2312
这个命令的作用就是在 Vim 中重新打开当前编辑的文件
,并强制指定其编码为 GB2312。当您遇到文件显示乱码,且怀疑其实际编码为 GB2312 时,可以使用这个命令尝试纠正显示问题。如果文件原本就是 GB2312 编码,执行此命令后,Vim 应该能够正确显示中文字符。
执行上述命令后,重新打开的文件就显示正常了
解决方式三
因为vi默认是 latin1
:Latin-1是一种单字节编码,主要用于西欧语言。以ISO 8859-1(Latin-1)编码打开文件
那么我们终端可以设置成ISO这种编码方式打开即可,但是这种方式若有中文的话,可能还是会乱码
解决方式四
如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱码的问题,那么你可以在
~/.vimrc 文件中添加以下内容:
set encoding=utf-8 fileencodings=ucs-bom,utf-8,cp936
这样就指定vi按照哪种方式打开文件
然后再用VI或VIM命令打开就正常了
扩展
1.vi或vim默认采用哪种编码方式打开文件?
vi
(或者更准确地说,现代系统中通常指代的vim
)在打开文件时,会遵循一套既定的流程来判断文件的编码方式。这个流程大致如下:
-
检查用户设置:
vim
首先查看用户在vimrc
配置文件中是否设置了fileencodings
选项。fileencodings
是一个以逗号分隔的编码列表,指定了vim
在打开文件时尝试识别的编码顺序。例如,用户可能设置了fileencodings=utf-8,latin1
,表示vim
先尝试以UTF-8编码打开文件,如果失败再尝试latin1编码。
-
检查BOM(Byte Order Mark) :
- 如果
fileencodings
列表中包含ucs-bom
,vim
会首先检查文件开头是否有BOM(Byte Order Mark)。BOM是某些Unicode编码(如UTF-8、UTF-16等)用来标识文件编码的一种特殊标记。如果文件以带有BOM的Unicode编码存储,vim
会根据BOM识别出正确的编码。
- 如果
-
逐个尝试
fileencodings
列表中的编码:- 若文件没有BOM或
fileencodings
中未包含ucs-bom
,vim
会按照fileencodings
列表中指定的顺序,依次尝试每个编码来打开文件。对于每个编码,vim
会读取文件的部分或全部内容,尝试解码并检查解码后的文本是否合理(如字符分布、字节序列规律等)。如果解码成功且文本看起来合理,vim
就认为找到了正确的编码,并以该编码显示文件内容。
- 若文件没有BOM或
-
默认编码:
- 如果用户没有在
vimrc
中设置fileencodings
,或者fileencodings
列表中的编码都无法成功解码文件,vim
会使用一个默认的编码列表来尝试打开文件。这个默认列表通常包含了常见的编码,如latin1
、utf-8
等,具体顺序和内容可能因vim
版本和系统环境有所不同。
- 如果用户没有在
-
自动检测:
- 在某些情况下,
vim
可能还具备自动检测编码的能力。这种情况下,它会使用内置的算法分析文件内容,尝试自动识别最可能的编码。这种功能可能作为fileencodings
选项的补充,或者在没有设置fileencodings
时启用。
- 在某些情况下,
2.GBK、GB2312和GB18030
GBK、GB2312和GB18030是中国制定的一系列汉字编码标准,它们之间的区别和联系主要包括以下几个方面:
区别
-
收录汉字数量:
- GB2312:基本集收录了6763个常用简体汉字和682个非汉字图形字符(包括符号、字母、日文假名等)。
- GBK:在GB2312的基础上进行了扩展,增加了大量生僻字、繁体汉字以及其他字符,总字符数超过20000个。
- GB18030:进一步扩大了字符集范围,不仅包含GBK的所有字符,还增加了对少数民族文字、更多生僻字、汉字部首以及一些专用符号的支持,总字符数超过27000个,满足更广泛的汉字使用需求。
-
编码空间:
- GB2312:每个字符使用两个字节表示,高字节范围是0xA1-0xF7,低字节范围是0xA1-0xFE。
- GBK:保留了GB2312的编码空间,同时扩展了编码范围,使用双字节和四字节两种编码方式。双字节部分与GB2312兼容,四字节部分用于编码新增字符。
- GB18030:沿用了GBK的双字节和四字节编码方式,且四字节编码范围进一步扩大,以容纳更多字符。
-
兼容性:
- GB2312:兼容ASCII码,即ASCII字符在GB2312中仍用单字节表示。
- GBK:向下兼容GB2312,即所有GB2312编码的字符在GBK中保持不变,同时还兼容ASCII。
- GB18030:向下兼容GBK和GB2312,即所有GB2312和GBK编码的字符在GB18030中都有对应的相同编码,同时也兼容ASCII。
联系
- 发展历程:这三个标准依次是汉字编码的升级版本,反映了随着计算机技术发展和汉字使用需求变化,中国对汉字编码体系的逐步完善。GB2312是最早的标准化汉字编码,GBK是对GB2312的扩充,以解决汉字数量不足的问题,而GB18030则是为了适应互联网时代更加多元化的文字处理需求,特别是对少数民族文字和生僻字的全面支持。
- 编码原则:三者都采用了双字节编码(GB2312全部是双字节,GBK和GB18030则同时有双字节和四字节编码),并且都设计为与ASCII码兼容,即ASCII字符在这些编码中可以直接使用其原编码,无需转换。
- 向下兼容性:GB18030、GBK和GB2312之间存在明显的向下兼容关系。这意味着使用更高版本编码的软件可以无障碍地处理用较低版本编码的文本数据,而不会出现乱码问题。这种兼容性使得新标准在推广时能平滑过渡,保护已有数据的兼容性。
3.vi编码参数说明
# 设置文件读写时的编码检测顺序,优先尝试UTF-8,然后是GB2312等
set fileencodings=utf-8,gb2312,gbk,gb18030,cp936
# 设置终端输出编码为UTF-8
set termencoding=utf-8
# 设置内部(Vim内部处理、交换文件等)使用的编码为UTF-8
set encoding=utf-8
4.排查系统乱码流程
- 查看当前系统字符集 locale
若不符合,则需要修改
临时修改:export LANG=zh_CN.UTF-8 # 以中文(简体)UTF-8编码为例
永久修改: echo 'export LANG=zh_CN.UTF-8' >> ~/.bashrc
然后执行 source ~/.bashrc 使更改生效
2.文件编码转换
如果系统字符集设置正确,但打开的某个特定文件显示乱码,可能是文件本身的编码与系统字符集不符。这时可以使用如iconv工具转换文件编码: iconv -f GB2312 -t UTF-8 input_file > output_file
3.终端模拟器设置
如果是在终端模拟器(如GNOME Terminal、Konsole、Terminator等)中遇到乱码,检查终端的字体设置,确保使用的字体支持显示所需字符集。通常可以在终端的设置选项中调整字体。
4.应用程序特定设置
对于某些应用程序(如文本编辑器、浏览器等),可能需要在应用内部单独设置字符编码。请查阅应用的文档或选项设置,确保其与系统字符集一致。
5.数据库相关问题
如果乱码出现在数据库连接或查询结果中,需要确保数据库的字符集设置、表的字符集、连接时指定的字符集(如通过NLS_LANG环境变量)等都与系统和应用程序的字符集相匹配。
6.网页浏览乱码
如果在浏览器中浏览网页出现乱码,检查浏览器的字符编码设置,确保其与网页的编码一致。通常可以在浏览器菜单中找到“查看”->“编码”选项进行调整。
4.四种执行shell脚本的方式
-
./script.sh
- 含义:这是使用相对路径直接执行一个具有可执行权限的shell脚本文件(如
script.sh
)的最常见方法。.
表示当前目录,/
用于分隔路径与文件名。 - 特点:要求脚本文件的第一行以
#!/bin/bash
(或其他合适的shell解释器路径)的形式包含一个shebang行,且文件拥有执行权限
(可通过chmod +x script.sh
赋予)。这种方式会创建一个新的子shell来执行脚本
,脚本中的变量、函数等定义不会影响到当前shell会话
。
- 含义:这是使用相对路径直接执行一个具有可执行权限的shell脚本文件(如
-
sh script.sh
- 含义:使用
sh
命令(通常指向/bin/sh
,即系统默认的Bourne shell或与其兼容的shell)来解释并执行指定的脚本文件。 - 特点:
无需脚本文件具有可执行权限
,但依然建议使用shebang行指定解释器。同样会在一个新的子shell中执行脚本,脚本环境与当前shell隔离
。
- 含义:使用
-
. script.sh
或source script.sh
- 含义:这两种方式均用于
在当前shell会话中直接执行脚本
,而不是在一个新的子shell中。.
是Bash shell中的内建命令(在其他shell中可能有不同的名称,如source
),用于读取并执行指定脚本的内容。 - 特点:脚本中的变量定义、函数创建、别名设置等会
直接影响当前shell会话
。不需要脚本具有可执行权限
,也不要求有shebang行(但建议有,以提高脚本的可移植性)。这种方式常用于在shell配置文件(如~/.bashrc
)中引入其他脚本,或者在交互式会话中临时加载脚本中的设置。
- 含义:这两种方式均用于
总结起来,这四种执行shell脚本的方式的主要区别在于:
- 执行环境:
./script.sh
和sh script.sh
会在新的子shell中执行,脚本环境与当前shell隔离;而.
(或source
)则在当前shell会话中执行,脚本环境与当前shell合并。 - 权限要求:
./script.sh
和sh script.sh
要求脚本具有可执行权限,而.
(或source
)则不要求。 - 作用域:在子shell中执行的脚本,其内部定义的变量、函数等只在子shell中有效,退出子shell后即失效;而在当前shell中执行的脚本,其定义的内容会直接影响当前shell会话,直到会话结束或被显式撤销。