如何输入特殊字符,以便Bash / Terminal了解它们?


18

假设文件夹中有一个名为的文件Näyttökuva.png(对于那些感兴趣的人,它在芬兰语中是“截屏”)。这是发生了什么:

$ ls
Näyttökuva.png

$ ls N*
Näyttökuva.png

$ ls Nä*
ls: Nä*: No such file or directory

这也会影响制表符自动完成。如果我开始键入ls N并按tab,则正确地将其展开为ls Näyttökuva.png。但是,如果我开始输入ls Nä制表键,则无济于事。

我怎么可以:

  • 配置bash / terminal以使其理解特殊字符
  • 输入特殊字符,以便bash / terminal理解它们?

在终端中,在“设置”选项卡中将编码设置为UTF-8,而“编码”选项卡处于其默认状态,即。UTF-8,Mac OS Roman,ISO拉丁1,ISO拉丁9,Windows拉丁1,ASCII,NextStep和某些亚洲编码已启用。


甚至是陌生人(尽管对于这个问题可能不是必需的):

如果输入ls N,请按tab,从末尾删除字符,直到读取为止,ls Nä然后再按tab一次,命令将扩展为ls Nättökuva.png[sic]。

如果我第二次尝试删除字母ls Nä,然后按Tab键,它将扩展为ls Nätökuva.png。第三轮扩大到ls Näökuva.png

出于某种原因,第4轮给出了结果ls Nä̈kuva.png(请注意变音符号而不是变音符号)。按Tab键将ls Nä̈给予ls Nä̈kuva.png每次。尽管如此,它的工作原理是:

$ ls Nä̈kuva.png
Näyttökuva.png

$ history 2
518  ls Näyttökuva.png 
519  history 2

Answers:


23

我认为bash在重音字符处理方式方面出现了一些异常。您可能想抢些爆米花,因为这会有点技术性...

Unicode允许某些重音字符以几种不同的方式表示:作为表示重音字符的“代码点”,或作为表示字符的无重音版本的一系列代码点,后跟重音。例如,“ä”既可以表示为U + 00E4(UTF-8 0xc3a4,带小写字母的拉丁小写字母1),也可以表示为U + 0061 U + 0308(UTF-8 0x61cc88,带小写字母的拉丁小写字母a +组合小写) )。

OS X的HFS +文件系统要求所有文件名都以其完全分解形式的UTF-8表示形式存储。在HFS +文件名中,“ä”必须编码为0x61cc88,而“ö”必须编码为0x6fcc88。

我很确定这里发生的事情是,当您在命令行中键入“Näyttökuva.png”时,它以预先合成的形式“键入”字符。创建文件后,文件系统将分解字符以进行存储。到目前为止一切都很好。但是,当您尝试使用以“Nä”开头的制表符补全时,我认为bash在搜索匹配项之前无法分解“ä”,当然也找不到任何东西。

为了说明不同之处,下面是一个示例,该示例说明了在命令行中仅键入“Näyttökuva.png”时使用的编码与将其存储为文件名并使用制表符补全来填充时使用的编码的示例:

$ printf Näyttökuva.png | xxd    # This time I pasted the it in from this web page
0000000: 4ec3 a479 7474 c3b6 6b75 7661 2e70 6e67  N..ytt..kuva.png
$ touch Näyttökuva.png           # Also pasted from the web
$ printf Näyttökuva.png | xxd    # This time I tab-completed it after N
0000000: 4e61 cc88 7974 746f cc88 6b75 7661 2e70  Na..ytto..kuva.p
0000010: 6e67                                     ng

现在,关于删除和重新制表时字符丢失的问题,我怀疑这是密切相关的。具体来说,我认为bash每次按Delete键都会“删除”一个代码点,但是每次按一下从Terminal窗口中删除一个字符。因为其中一个删除的字符(这次为“ö”)由两个代码点组成,但是只有一个字符,所以终端显示不同步。尝试对整个文件名进行制表符填充,然后将其删除回“Näytt”,然后重新进行制表符填充:bash似乎认为仅删除了组合音符,而不是整个“ö”,因此它重新添加了组合音符,但这一次它附加到“ t”上:

$ echo Näytkuva.png 
Näyttökuva.png

请注意,当我按回车键时,bash实际上具有整个文件名。只是终端显示感到困惑。

TL; DR bash在处理可分解带有重音符号的字符时存在一些错误。

编辑:经过一番思考,我认为唯一完整的解决方案是修复bash(/等待其开发人员对其进行修复)。也许还有一种以分解形式输入字符的方法,但是我不知道那是什么。但是我确实找到了一些解决方法:

  1. 从Finder中拖放文件会以正确的格式粘贴。由于Finder从文件系统获取文件名,因此它已经被分解,因此可以正常工作。

  2. 您实际上可以使用制表符完成重音字符本身。例如,如果您键入“ Na”,然后输入制表符,则它将匹配“Näyttökuva.png”,因为“ä”的规范分解以“ a”开始。但是,如果您在同一目录中有一个名为“ Narwal.gif”的文件,那将不会很有帮助...

  3. 我尚未对此进行测试,但是如果将Tab键绑定到菜单完成键而不是完整键,则应该让您选择可能的匹配项,以便即使您无法输入下一个字母也可以选择所需的匹配项。(或者您可以将其绑定到其他按键,因此只能在需要时使用它。)

  4. 为了解决终端显示不同步的问题,您可以将某些内容绑定到redraw-current-line上 -不会阻止问题的发生,但是它将为您提供一种重新同步显示的方法。


谢谢,我喜欢爆米花。我认为您已经确定了问题的原因:使用$ echo -e "N\xC3\xA4*" | ls(回波给出Nä*)结果Näyttökuva.png。Mac OS中的其他外壳也存在该问题。与如zsh中ls N得到自动完成ls Na<0308>ytto<0308>kuva.png
杰瑞Keinänen

我还在ls Nä*Xubuntu中尝试了自动补全和bash,它可以正常工作,因此它在键盘,OS X和终端之间出现了错误。我也在Bootcamp分区中进行了测试,但是问题仍然存在(即,仅HFS +文件不会发生此问题)。
JariKeinänen2011年

(现在,您看到了有关变通方法的编辑)至少前两个工作。#2很有趣:自动补全Na可以,但是Nay不可以(尽管可以理解,因为实际上¨a和之间y。在Xubuntu ls Na*中不起作用(虽然Nä*可以用,所以这实际上不是问题)。更换äö使用a?,并o?ls Na?y*当然这会增加不确定性,但它可能在某些情况下,来方便。
杰瑞Keinänen

2
它在Xubuntu中工作的原因可能仅仅是文件系统使用与终端接口相同的形式。如果您ls N* | xxd在Xubuntu中这样做,它会给出组合字符还是分解字符?
戈登·戴维森

假设Xubuntu以组合形式存储文件名,请尝试运行命令touch $'Na\xcc\x88ytto\xcc\x88kuva.png'并查看会发生什么-我猜是它将创建一个名称非常相似的新文件。
戈登·戴维森

4

这是一个古老的问题,没有明确的答案。只是解决方法。

但是,我结合了此旧指南中的一些信息,并按照此处的建议和指示进行操作:

我在Snow Leopard中安装了更新的bash。安装完成后,bash可以正常工作!(Snow Leopard随附3.2.48(1),而MacPorts已安装4.2.45_1)。记住要在/etc/shells运行中进行更改chsh

另外,由于其他一些说明,我在.inputrc

set meta-flag on
set input-meta on
set output-meta on
set convert-meta off

不知道是否需要它们才能正常操作。


您说对了:bash 4.2可以完成(在此处ä是预先组成的),Näyttökuva.png但是bash 3.2却没有。
Lri 2013年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.