我试图学习变量在 gnome-terminal 中的行为方式$LANG
(及其字符编码首选项)。我一直使用 iso8859-1 (latin1) 作为我的主要字符集,并且我的所有文件名都是这样编码的。
对于以下测试,我将创建ls -l
文件名中包含西班牙语重音字符的目录:
情况1:
- 为 ISO-8859-1 配置的 gnome 终端
LANG
设置为“en_US-iso8859-1”- 结果:我正确地看到了所有文件
案例#2:
- gnome 终端配置为 UTF-8
LANG
设置为“en_US-iso8859-1”- 结果:我看到所有西班牙语字符都是垃圾字符。这是预期的,因为我更改了终端的字符编码
案例#3:
- 为 ISO-8859-1 配置的 gnome 终端
LANG
设置为“en_US-UTF-8”- 结果:我看到所有西班牙语字符都是垃圾字符。
为什么在最后一种情况下我看到乱码?不应该输出LS将文件名直接发送到 gnome-terminal 吗?由于 gnome-terminal 配置为 ISO-8859-1,我希望它们看起来是正确的。
有一瞬间我想,也许 bash 正在考虑我的$LANG
变量并执行一些转换。然后我将终端切换为UTF-8,但我仍然看不到正确的字符。我什至将 ls 的输出通过管道传输到 xxd,令我惊讶的是,我仍然看到按原样编码的文件:ISO-8859-1。
总结:如果我的列表包含 ISO-8859-1 字符,并且我的终端仿真器配置为相同的字符编码:LANG
否则设置时谁在进行转换?
感谢您的任何帮助,您可以提供。
克拉科尼亚
答案1
您的设置LANG
必须与终端的设置匹配。更准确地说,您的(字符编码)设置LC_CTYPE
必须与终端的编码匹配,其他区域设置不需要匹配。终端的编码通常由终端仿真器的选项指定,而不是由区域设置变量指定。它LC_CTYPE
结合了两个指示:它告诉应用程序在终端上使用什么编码(输入和输出),并告诉应用程序对文件使用什么编码。在情况 2 和 3 中,您指定ls
以与终端不同的编码显示输出,因此输出是乱码。
如果您在不同时间使用 UTF-8 和 latin-1 编码,请将终端配置为使用 UTF-8。这应该会导致它设置LC_CTYPE
为指示 UTF-8 的值;不要覆盖此设置。 (如果终端模拟器未设置LC_CTYPE
,请在 shell 启动文件或整个会话中覆盖它。)要在 UTF-8 终端中使用 latin-1 数据,请使用luit
(包含在 X 实用程序套件中)。
LC_CTYPE=en_US.iso88591 luit
(您可以使用具有相同编码的任何其他区域设置,例如LC_CTYPE=es_ES.iso88591 luit
。)
答案2
在情况 #2 和 #3 中,您混合了两种不同的编码 UTF-8 和 Latin-1。在情况 #1 中,您对两者都使用 Latin-1,所以不会有问题。
该ls
命令(以及所有其他运行良好的程序)使用 LANG 设置来确定编码。
您可以混合两种不同的语言,但是您不应混合两种不同的编码。
确保 LC_* 环境变量也使用与 LANG 变量相同的编码。
根据经验,您现在应该将系统配置为仅使用 UTF-8。
如果您必须编辑老式数据文件(例如 java 属性),您应该使用专门的编辑器(例如 java ide)或使用iconv
“recode..”等工具确保编码。
答案3
这可能超出了您的需要,但是......
事实证明,在 RHEL5 中,甚至可能更早的版本中,许多手册页都出于某种不可预见的原因,被 ascii 化了。也就是说,原始手册页已从其本机字符集转换为 7 位 ASCII。无论您对 LC 和 LANG 做什么,手册页都会latin1
生成一个实际上毫无用处的手册页。其中所有特殊(8 位)字符均已替换为 7 位占位符(通常为??
)。我觉得这很搞笑。
但utf8
这些手册页的版本可能存在于特定于语言的目录中。诀窍是用他们的正确名字来询问他们。例如,latin1 实际上是iso_8859-1
.如果你在上面做了一个手册页,并且你的 LANG 设置是正确的,你就会看到你所期望的;手册页位于特定于语言的子目录 ( en/man7/iso_8859-1.7
) 中。但如果您出于某种原因询问iso-8859-1
,您将得到 ASCII 版本。