bash 中不再显示非 ascii 字符

Ole*_*nge 4 bash locale interactive

更新:这不是文件系统问题。

\n\n

我以前可以输入:

\n\n
$ echo k\xc3\xb8dp\xc3\xa5l\xc3\xa6g\n
Run Code Online (Sandbox Code Playgroud)\n\n

但现在 bash/zsh 将其更改为:

\n\n
bash$ echo kddddddddplg\nzsh$ echo k<c3><b8>dp<c3><a5>l<c3><a6>g\n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以运行cat并输入 \'k\xc3\xb8dp\xc3\xa5l\xc3\xa6g\' 没有问题:

\n\n
$ cat\nk\xc3\xb8dp\xc3\xa5l\xc3\xa6g\nk\xc3\xb8dp\xc3\xa5l\xc3\xa6g\n
Run Code Online (Sandbox Code Playgroud)\n\n

这都是在这个环境下:

\n\n
$ locale   \nLANG=C\nLANGUAGE=C\nLC_CTYPE="C"\nLC_NUMERIC="C"\nLC_TIME="C"\nLC_COLLATE="C"\nLC_MONETARY="C"\nLC_MESSAGES="C"\nLC_PAPER="C"\nLC_NAME="C"\nLC_ADDRESS="C"\nLC_TELEPHONE="C"\nLC_MEASUREMENT="C"\nLC_IDENTIFICATION="C"\nLC_ALL=C\n
Run Code Online (Sandbox Code Playgroud)\n\n

并在此:

\n\n
$ locale \nLANG=da_DK.utf8\nLANGUAGE=da_DK.utf8\nLC_CTYPE="da_DK.utf8"\nLC_NUMERIC="da_DK.utf8"\nLC_TIME="da_DK.utf8"\nLC_COLLATE="da_DK.utf8"\nLC_MONETARY="da_DK.utf8"\nLC_MESSAGES="da_DK.utf8"\nLC_PAPER="da_DK.utf8"\nLC_NAME="da_DK.utf8"\nLC_ADDRESS="da_DK.utf8"\nLC_TELEPHONE="da_DK.utf8"\nLC_MEASUREMENT="da_DK.utf8"\nLC_IDENTIFICATION="da_DK.utf8"\nLC_ALL=da_DK.utf8\n
Run Code Online (Sandbox Code Playgroud)\n\n

csh不改变\'k\xc3\xb8dp\xc3\xa5l\xc3\xa6g\'。

\n\n

如何恢复旧行为,以便我可以输入 \'k\xc3\xb8dp\xc3\xa5l\xc3\xa6g\'?

\n\n

运行其中任何一个都会产生旧的行为:

\n\n
LC_ALL=en_GB.utf-8 luit\nLC_ALL=da_DK.utf-8 luit\nLC_ALL=en_GB.iso88591 luit\nLC_ALL=da_DK.iso88591 luit\n
Run Code Online (Sandbox Code Playgroud)\n\n

但仅限于该单一会话。

\n\n

这:

\n\n
$ od -An -vtx1\n\xc3\xb8\n
Run Code Online (Sandbox Code Playgroud)\n\n

给出:

\n\n
 c3 b8 0a\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以看来从 Konsole 到 bash 的输入是 UTF8。

\n\n
$ konsole --version\nQCoreApplication::arguments: Please instantiate the QApplication object first\nQt: 5.5.1\nKDE Frameworks: 5.18.0\nKonsole: 15.12.3\n\n$ bash --version\nGNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)\nCopyright (C) 2013 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\nThis is free software; you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n\n$ zsh --version\nzsh 5.1.1 (x86_64-ubuntu-linux-gnu)\n\n$ dpkg -l csh\nDesired=Unknown/Install/Remove/Purge/Hold\n| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend\n|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)\n||/ Name              Version       Architecture  Description\n+++-=================-=============-=============-========================================\nii  csh               20110502-2.1u amd64         Shell with C-like syntax\n
Run Code Online (Sandbox Code Playgroud)\n

Sté*_*las 5

我想说,很可能您的终端配置错误,并以某些单字节字符集发送和显示字符,考虑到您显示的示例字符而不是区域设置的字符集,可能是 ISO8859-1 或 ISO8859-15。

\n\n

C 语言环境中通常没有\xc3\xb8, \xc3\xa5,\xc3\xa6字符,并且这些字符的 ISO8859-1(5) 编码(0xf8、0xe5、0xe6)不会形成 UTF-8 中的有效字符。像 readline 或 zle 这样的行编辑器需要将它们解码为字符,因为它们需要知道有多少字节组成显示列,以便它们可以正确定位光标。

\n\n

此外,在大多数系统上使用 ASCII 的 C 语言环境中,由于 ASCII 中没有设置第 8 位的字符因此第 8将被理解为bash含义Meta。0xF8 将被理解为Meta+x(0x78 (x) | 0x80),因为这是某些终端发送的内容Alt+xMeta+x上发送的内容。

\n\n

虽然 Mx 默认情况下不绑定到任何内容bash\xc3\x9f但会被理解为 M-_ 并插入最后一个单词。您可以通过以下方式将其关闭:

\n\n
bind 'set convert-meta off'\n
Run Code Online (Sandbox Code Playgroud)\n\n

像这样的 shellcsh太古老了,甚至不知道字符可能由几个字节组成,或者占据除单个列宽度之外的任何内容,因此它们不会打扰。

\n\n

要验证该理论,请运行:

\n\n
od -An -vtx1\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后输入这些字符,^D^D然后查看您看到的编码。如果你看到 0xf8 \xc3\xb8,那就意味着我是对的。如果您看到 0xc3 0xb8,这是 UTF-8 编码,\xc3\xb8则意味着我错了。

\n\n

或者将区域设置更改为da_DK.iso88591(检查locale -a系统上区域设置的确切名称)并查看是否效果更好。

\n\n

现在,为什么您的终端可能会发送这些字符的错误编码,可能是在字符集为 iso8859-1 的语言环境中启动的。也许它被配置为忽略区域设置并使用特定的字符集(在其配置中查找字符集编码)。或者您可能是ssh从另一个系统输入的,其中区域设置使用 ISO8859-1(5) 作为其字符集。

\n\n

如果从 UTF-8 终端运行以下命令,我可以重现该行为:

\n\n
LC_ALL=en_GB.iso885915 luit\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后从内部luit将区域设置更改为CUTF-8 区域设置并输入非 ASCII 字符。

\n