短版(TL;DR)
我有 2 个小的单行文件,看似相同:
$ cat f1 f2
./cconv.sh 100 EUR USD
./cconv.sh 100 EUR USD
但它们不是,大小有 1 个字节的差异:
$ ls -l f1 f2
(...) 24 oct. 30 16:19 f1
(...) 23 oct. 30 16:19 f2
$ diff f1 f2
1c1
< ./cconv.sh 100 EUR USD
---
> ./cconv.sh 100 EUR USD
我曾经dhex
计算出十六进制的差异。看起来 :
f1
完成c2 a0 55 53 44 0a
f2
完成20 55 53 44 0a
有人知道这里发生了什么吗?有什么区别,更重要的是,它来自哪里?这是包含 2 个文件的 zip 文件的链接,以及dhex
结果的屏幕截图。
长版(附加说明)
这 2 个文件摘自我的~/.bash_history file
.
我注意到我的贝壳有一种非常奇怪的行为。采用以下非常基本的脚本:
#!/bin/sh
echo $#
echo "$1"
echo "$2"
echo "$3"
exit 0
在某些情况下(但哪些 ???),它不会将空格作为参数分隔符:
$ ./cconv.sh 100 EUR USD
2
100
EUR USD
但有时它会按预期工作:
$ ./cconv.sh 100 EUR USD
3
100
EUR
USD
它让我发疯!我花了几个小时试图弄清楚发生了什么。以下是我为缩小范围所做的一些测试:
- 我在一台装有 Debian 11、Gnome 3.38 的笔记本电脑上工作。但我碰巧也有一台操作系统完全相同的虚拟机(D11,G3.38),在虚拟机中一切正常。所以很明显,我一定是对我的裸机笔记本电脑做了一些事情,让它表现不佳。但是什么???
- 我注意到这个问题只发生在图形会话中。如果我打开一个 tty (Ctrl+Alt+F n ),它工作正常
- 我怀疑我的终端模拟器。但是在不同的模拟器中行为是相同的(我试过 Gnome Terminal、Terminator 和 Konsole,结果相同)
- 我怀疑是贝壳。但是 Bash 或 Dash 的行为是相同的
- 我禁用了我能想到的所有自定义:
- 我暂时删除了
/etc/bashrc
,/etc/profile
,/etc/inputrc
和/etc/rc.local
- 我暂时删除了
~/.bashrc
,~/.profile
并且~/.inputrc
- 我禁用了所有 Gnome Shell 的扩展
- 我暂时删除了
- 我什至怀疑是键盘,并插入了 USB 键盘。结果相同。
我真的很困惑,不知道发生了什么。我终于注意到 2 个命令之间的细微差别~/.bash_history
:一个来自我的 Gnome 会话,另一个来自我的 tty 会话。显然存在差异,但究竟是什么,可能是什么原因?
c2 a0
是不间断空格字符的 UTF-8 编码。它通常看起来像一个常规空格,但不被 shell 识别为空格。在一些键盘映射中,像AltGr+Space或Option+这样的东西Space会产生一个不间断的空格。AltGr如果您的键盘映射在or后面也有例如管道字符,这很有趣Option,这使得键入
|<nbsp>
而不是更容易|<sp>
,给您这样的错误:(我认为 SE 会将 nbsp 折叠到常规空间,因此如果从此处复制粘贴,您可能不会收到错误消息。)
如果您从其他工具复制并粘贴参数,您可能会从那里得到奇怪的格式,但这取决于程序。
有关不生成字符的一些解决方案,请参阅在 shell 中处理 nbsp字符。