简短版本(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
有人知道这里发生了什么事吗?有什么区别,更重要的是,它从哪里来?以下是链接包含这两个文件的 zip 文件以及dhex
结果的屏幕截图。
长版(附加说明)
这两个文件是我的~/.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+Fn),效果很好
- 我怀疑我的终端模拟器。但不同模拟器中的行为是相同的(我尝试了 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 会话。显然是有区别的,但是到底是什么,以及可能的原因是什么?
答案1
c2 a0
是 UTF-8 编码不间断空格字符。它通常看起来像一个常规空格,但 shell 不会将其识别为空白。
在一些键盘映射中,类似AltGr+Space或Option+ 的东西Space会产生不间断的空格。如果您的键盘映射在AltGr或后面还有管道字符Option,这会很有趣,这样可以更轻松地键入|<nbsp>
而不是|<sp>
,从而给出如下错误:
$ echo foo | grep .
bash: grep: command not found
(我认为 SE 将 nbsp 折叠到常规空间,因此如果从此处复制粘贴,您可能不会收到错误。)
如果您从其他工具复制并粘贴参数,您可能会从那里得到奇怪的格式,但这取决于程序。
看shell中处理nbsp字符一些不产生角色的解决方案。