我可以column
使用制表符作为字段分隔符:
$ printf "a\tb\tc\n" | column -s $'\t' -t
a b c
但使用空分隔符似乎不起作用:
$ printf "a\0b\0c\n" | column -s $'\0' -t
column: line too long
为了确认,空分隔符确实存在:
$ printf "a\0b\0c\n" | xxd
00000000: 6100 6200 630a a.b.c.
这里可能出了什么问题?
任何执行的命令都不能像在
execve()
系统调用中那样在其参数中包含 NUL ,命令行参数都是 NUL 分隔的字符串。$'\0'
仅适用于 zsh shell 以及内置命令或函数的参数(execve()
不涉及其中)。在支持
$'...'
ksh93 中的引用运算符的其他 shell 中,其内部的 a\0
(或\u0000
、\x0
、x{0}
或\c@
,\C-@
这取决于 shell,它们是 NUL 的其他可能表示形式)后面的内容将被丢弃 ($'a\0b'$'c\0d'
与 相同ac
)¹ ²。无论如何,在所有 shell 中external-command $'something\0'
都与external-command something
和external-command $'\0'
相同。external-command ''
要将 NUL 传递给命令,必须使用某种形式的约定以另一种方式进行。例如,可以是
\0
字面意思(如在awk -v nul='\0'
或printf
的格式参数中)或%00
(如 URI),另请参阅bash、zsh 或最新版本的 ksh93 或 GNU 的''
将其解释为 NUL 。read -d
cut -d
column
在util-linux
(基于相应的 BSD 命令) 中发现的不支持上述任何内容,并且与大多数传统实用程序一样(与大多数 GNU 实用程序相反),甚至不支持在其输入中使用 NUL,因为它在内部使用 NUL 分隔的字符串(C 字符串)。沒有
b c
。为了解决这个问题,你可以在传递之前将 0 字节更改为 1 字节(或输入中未找到的任何其他字节值),
column
然后再改回来:¹已添加到该语言
$'...'
的 POSIX 规范 2024 版中sh
,并且两种行为都是允许的。²
fish
和es
是两个(非 POSIX 类)shell,它们支持引号外的\ooo
八进制转义序列(也\xhh
用于),并且它们的行为类似,除了 的最新版本会为或发出错误。es
es
bad backslash escape
\0
\x0