以下代码将打印“a”到终端宽度,然后打印制表符,最后打印“b”。我测试了 Ubuntu 的默认 Gnome 终端和 Terminator,它们将所有“a”和“b”显示在同一行上,作为一个单词,没有制表符。复制它们也不会显示制表符。当我们再打印一个“a”(将 0 更改为 1)时,也会发生同样的情况。这是错误吗?
printf '%'$(($(stty size | cut -d ' ' -f 2)+0))'sb\n' $'\t' | tr ' ' 'a'
答案1
这也是 的行为xterm
,它被广泛认为是终端仿真的事实标准;而且我很确定它也得到了这些终端仿真器遵循的相应标准的支持。
TAB 不是可打印字符(isprint(9)
返回 0),[并且在我看来,将 TAB 存储在文本文件中的做法是整个计算机世界中的一大错误,不仅仅是因为它给终端仿真带来的麻烦;但这是另一天的辩论,我不想在这里开始制表符与空格之间的争论:)]
TAB 是一个控制字符,可将同一行中的光标移动到下一个 TAB 停止位。它与终端支持的所有其他各种光标移动转义序列类似。
有趣的是,您还可以注意到 TAB 不会擦除下面的字符。如果它跳过了任何实际内容,那么它会保持不变,完全破坏视觉效果,与您可能期望的复制粘贴不同。
市面上的许多终端仿真器不会将 TAB 复制到剪贴板,而是复制空格(我猜跳过处于“已删除”状态的单元格会将它们转换为空格)。这是 VTE(GNOME Terminal 和 Terminator 使用的终端仿真小部件)中的一个特殊特性,可能也存在于其他一些终端仿真引擎中,用于在特定情况下保留 TAB 字符(例如,如果它没有跳过已经存在的字符)。
尽管我和您一样不喜欢当前的行为,并且更希望 TAB 跳转到下一行并在复制粘贴或在调整大小时重新换行时保留,但我担心这种偏离标准的行为可能会导致各种应用程序中出现各种各样的错误。
TAB 不是可打印字符,而是控制指令。就像任何其他不可打印字符(包括转义序列)一样,除非您确切知道自己在做什么,否则不应将它们发送到终端。不幸的是,终端(及其支持标准)的这种期望,以及文本文件中广泛使用 TAB 并期望cat
“正常工作”确实无法很好地协调。