单位分隔符 ASCII 字符(ASCII 31,八进制 37)在 Vim 中可见为^_
.但是,如果我将相同的文件打印到终端,则该字符是不可见的。这会导致一行上的字段粘在一起:
# In Vim and less:
first field^_second field^_last field
# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field
# print 2nd field with awk
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field
我想我可以使用 cat -v 使单位分隔符可见:
cat -v delim.txt
first field^_second field^_last field
但这是比较麻烦的。为什么单位分隔符在 Bash shell 中打印到 stdout 时没有可见的表示形式?我什至无法正确复制和粘贴 shell 输出;单位分隔符在此过程中丢失。
答案1
单位分隔符 ( US
) 字符,也称为IS1
,属于cntrl
字符类,并且是不是在里面print
字符类中。它是一个控制字符,用于将文本组织成组,对于旨在利用该信息的程序。一般来说,不可打印的字符在不同的程序或环境中可能会有不同的解释和呈现。
您看到它在 Vim 中表示的原因^_
是因为 Vim 是一个交互式编辑器。只要将正确的二进制字符写入磁盘,它就可以随意呈现不可打印的字符。
您无法在 shell 中获得相同的行为,因为 Unix shell 程序是为了操作纯文本并将纯文本相互传递而编写的。当您cat
创建文件时,写入终端的文本必须是文件中实际的内容。
这样就将其留给终端设备来解释该字符。事实证明,一些终端模拟器做使US
角色与其他角色不同。在gnome-terminal
(或任何vte
基于 的终端)中,字符将呈现为包含十六进制代码的框001F
。在xterm
or中rxvt
,该字符确实是不可见的。
答案2
单位分隔符的 ASCII 范围为控制字符,因此没有(或通常不应该)有视觉表示。
Vim 和其他一些编辑器会显示它们,以便您可以编辑它们。正如您所注意到的,cat -v
它也显示出来。手册页显示,这-v
是 的缩写形式--show-nonprinting
,这会导致它用可打印表示替换非打印字符,这不是文件的原始内容,因此如果输出实际上是另一个程序,可能会导致麻烦。
您看到的表示形式已经暗示它是一个控制字符:前面带有 a 的字符^
是Ctrl+ 字符的常见表示法,它是在终端中生成该字符的组合键。例如,Ctrl+可以让你在 vim 中输入单位分隔符。_但另一个编辑器或某些 GUI 查看器可能会显示十六进制代码、占位符或完全不同的东西。
由于您的终端不打印控制字符,因此在选择文本时也不会复制它(换行符和制表符等空白字符在这里是一个例外,它们也是控制字符)。复制时通常会忽略的终端中控制字符的另一个示例是颜色代码,它是一个ESC
字符,后跟用于为文本着色的代码。
因此,要在终端上显示字符,除了使用用一些可打印字符替换单位分隔符的程序之外,没有其他方法。
答案3
如果你想改变的话,在其他(非常好的)答案的边缘一点仅有的显示文件内容时的控制字符^_
,您可能想要音译它使用tr
实用程序(以及一些 bash 兼容语法):
# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'
如果您需要用“扩展”形式替换该控制字符,则需要sed
:
# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g
请注意语法$'\cX'
:此语法通知您的(bash 兼容 shell)替换相应的控制字符。看维基百科的控制字符别名列表使用“插入符号”。如果您不喜欢这种语法,您可能更喜欢使用八进制$'\037'
或十六进制$'\x1f'
表示法。