我有大量zsh
基于 CLI 任务的脚本,其中大部分是在 FreeBSD 和 MacOS(均为 BSD Unix 版本)上开发的。
我最近一直在使用 Ubuntu,发现我的一些脚本有问题。我尚未修复的几个脚本之一依赖于vis(1)
,一种将不可打印字符转换为其“可见”等效字符的常用实用程序。例如,BELL
人物变得好看^G
又难看“逃脱“经过 ing 和管道传输后就变成\e
了。echo
vis
在调试屏幕输出时它非常方便,否则会弄乱甚至锁定屏幕。
通常,当没有与基本系统一起安装时(例如在 FreeBSD 上),vis(1)
它会捆绑在 terminfo 包中,就像在 MacOS 上一样,甚至可以在 Homebrew 上使用。
但是我在 Linux 上找不到它,在我的发行版的 terminfo 包中也找不到它。事实上, vis(1)
似乎是某种vi
克隆在 Ubuntu 上!
我能找到的最接近的东西是libbsd-devvis.h
包,但该包只包括系统调用的库、手册页和 C 头定义strvis(3)
和strunvis(3)
。
Linux 上是否有具有类似功能的实用程序?我应该安装哪个软件包才能获得它;最好是适用于 Ubuntu 的?
答案1
事实证明,存在一种 100% 可移植的解决方案,并且还有一个额外的好处,就是不依赖于包装者和维护者的任何外部实用程序!
在浏览了厚厚的zsh
手册页之后,我发现了一个不太明显而且可能鲜为人知的功能。
因此我们有括号扩展对于变量(或用zsh
-speak 来说的参数),在对变量进行括号扩展时,可以使用一大堆标志,而且使用这些标志可以完成非常方便的事情。因此,如果我将难看的 apnd 和可能锁定终端的 termcaps 存储在变量中,我所要做的就是在ing ing(V)
时或在某个时候分配给新变量时使用该标志。它将具有与上述实用程序完全相同的效果。在内部,它实际上是重新实现的。所以我的解决方案是这样的:echo
print
vis(1)
strvis(3)
zmodload zsh/terminfo
typeset terminal_reset_sequence=$terminfo['rs2'] #toxic! locks terminal if echoed!
echo ${(V)terminal_reset_sequence} # Perfectly safe like piping trough vis(1)
作为奖励,我发现了(Q)
和标志,它们将对包含斜杠、八进制数、单引号和双引号的任何字符串(z)
执行正确的 shell 引用 ( )。神奇地使它们成为 shell 安全的,而如果我理解正确的话,将“(Q)
(z)
剥去“在任何嵌套引用的字符串上以 shell 安全的方式进行一级引用。真希望我两年前就知道这些!:C
答案2
GNU coreutilscat
有这个(臭名昭著的)内置函数 – 如果你不介意它破坏 UTF-8:
cat -v
中有一个类似的函数sed
,但它也将行折叠为 80 个字节:
sed -n l
更便携的东西是:
perl -p -e 's/[^\t\n\x20-\xFF]/sprintf("\\x%02X", ord($&))/ge'
我认为这可以更好地处理 Unicode:
perl -C -p -e 's/[^\n\P{Other}]/sprintf("\\x{%04X}", ord($&))/ge'
答案3
我还没有vis
在 BSD 上使用过,但我发现它对于确定 Linux 终端中的 ASCII 转义码非常有用。它甚至可以捕获和显示、、和箭头键showkey -a
的 ASCII 转义码。Backspace
Ctrl+C
Ctrl+D
Enter