更新:这不是文件系统问题。
我以前可以输入:
$ echo kødpålæg
但现在 bash/zsh 将其更改为:
bash$ echo kddddddddplg
zsh$ echo k<c3><b8>dp<c3><a5>l<c3><a6>g
我可以cat
毫无问题地运行并输入“kødpålæg”:
$ cat
kødpålæg
kødpålæg
这都是在这个环境下:
$ locale
LANG=C
LANGUAGE=C
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C
并在此:
$ locale
LANG=da_DK.utf8
LANGUAGE=da_DK.utf8
LC_CTYPE="da_DK.utf8"
LC_NUMERIC="da_DK.utf8"
LC_TIME="da_DK.utf8"
LC_COLLATE="da_DK.utf8"
LC_MONETARY="da_DK.utf8"
LC_MESSAGES="da_DK.utf8"
LC_PAPER="da_DK.utf8"
LC_NAME="da_DK.utf8"
LC_ADDRESS="da_DK.utf8"
LC_TELEPHONE="da_DK.utf8"
LC_MEASUREMENT="da_DK.utf8"
LC_IDENTIFICATION="da_DK.utf8"
LC_ALL=da_DK.utf8
csh
不改变 'kødpålæg'。
我怎样才能恢复原来的行为,以便我可以输入“kødpålæg”?
运行其中任何一个都会产生旧的行为:
LC_ALL=en_GB.utf-8 luit
LC_ALL=da_DK.utf-8 luit
LC_ALL=en_GB.iso88591 luit
LC_ALL=da_DK.iso88591 luit
但仅限于该单一会话。
这:
$ od -An -vtx1
ø
给出:
c3 b8 0a
所以看来从 Konsole 到 bash 的输入是 UTF8。
$ konsole --version
QCoreApplication::arguments: Please instantiate the QApplication object first
Qt: 5.5.1
KDE Frameworks: 5.18.0
Konsole: 15.12.3
$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ zsh --version
zsh 5.1.1 (x86_64-ubuntu-linux-gnu)
$ dpkg -l csh
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=================-=============-=============-========================================
ii csh 20110502-2.1u amd64 Shell with C-like syntax
答案1
我想说,您的终端很可能配置错误,并以某些单字节字符集发送和显示字符,考虑到您显示的示例字符而不是区域设置的字符集,可能是 ISO8859-1 或 ISO8859-15。
C 语言环境中通常没有ø
, å
,æ
字符,并且这些字符的 ISO8859-1(5) 编码(0xf8、0xe5、0xe6)不会形成 UTF-8 中的有效字符。像 readline 或 zle 这样的行编辑器需要将它们解码为字符,因为它们需要知道有多少字节组成显示列,以便它们可以正确定位光标。
此外,在大多数系统上使用 ASCII 的 C 语言环境中,由于 ASCII 中没有设置第 8 位的字符,因此第 8位将被理解为bash
含义Meta。 0xF8 将被理解为Meta+x(0x78 (x) | 0x80),因为这就是某些终端在Alt+x或上发送的内容Meta+x。
虽然 Mx 默认情况下不绑定到任何内容bash
,ß
但会被理解为 M-_ 并插入最后一个单词。您可以通过以下方式将其关闭:
bind 'set convert-meta off'
像这样的 shellcsh
太古老了,甚至不知道字符可能由几个字节组成,或者占据除单个列宽度之外的任何内容,因此它们不会打扰。
要验证该理论,请运行:
od -An -vtx1
然后输入这些字符,然后^D^D
查看您看到的编码。如果你看到 0xf8 ø
,那就意味着我是对的。如果您看到 0xc3 0xb8,这是 UTF-8 编码,ø
则意味着我错了。
或者将区域设置更改为da_DK.iso88591
(检查locale -a
系统上区域设置的确切名称)并查看是否效果更好。
现在,为什么您的终端可能会发送这些字符的错误编码,可能是在字符集为 iso8859-1 的语言环境中启动的。也许它被配置为忽略区域设置并使用特定的字符集(查找字符集或者编码在其配置中)。或者您可能是ssh
从另一个系统输入的,其中区域设置使用 ISO8859-1(5) 作为其字符集。
如果从 UTF-8 终端运行以下命令,我可以重现该行为:
LC_ALL=en_GB.iso885915 luit
然后从内部luit
将区域设置更改为C
UTF-8 区域设置并输入非 ASCII 字符。
答案2
您的cat
测试表明终端连接是 8 位干净的。所以这似乎是一个可能的区域设置问题。
请运行locale -a
以验证您选择的语言环境“da_DK.utf8”是否存在;如果它没有列出,并且您使用的系统属于 Debian/Ubuntu 系列,则可能需要取消注释/etc/locale.gen
,然后locale-gen
以 root 身份运行。
另外,某些 shell 版本无法动态切换语言环境,但仍使用语言环境设置最初是从其父进程继承的。如果是这种情况,那么运行LC_CTYPE=da_DK.UTF-8 bash
将仅在该特定会话期间恢复所需的行为。如果确实如此,则将系统默认区域设置更改为任何受支持的 UTF-8 区域设置,然后重新启动可能会有所帮助:这将更改负责处理登录和启动 shell 的进程的区域设置。