我有一个程序可以打印包含空字节\0
和特殊字符(如\x1f
和换行符)的内容。例如:
someprogram
#!/bin/bash
printf "ALICE\0BOB\x1fCHARLIE\n"
给出这样一个程序,我想以一种方式读取它的输出,使得所有这些特殊字符都被捕获在一个外壳变量output
中。因此,如果我运行:
echo $output
因为我没有给出-e
,所以我希望输出为:
ALICE\0BOB\x1fCHARLIE\n
如何实现?
我的第一次尝试是:
output=$(someprogram)
但是我得到了没有特殊字符的回显输出:
./myscript.sh: line 2: warning: command substitution: ignored null byte in input
ALICEBOBCHARLIE
我也尝试如下使用read
:
output=""
while read -r
do
output="$output$REPLY"
done < <(someprogram)
然后我摆脱了警告,但是输出仍然缺少所有特殊字符:
ALICEBOBCHARLIE
所以,如何以在生成的字符串中包含所有特殊字符的方式捕获someprogram
的输出?
编辑:请注意,bash中可能有这样的字符串:
$ x="ALICE\0BOB\x1fCHARLIE\n"
$ echo $x
ALICE\0BOB\x1fCHARLIE\n
所以那不应该是问题。
您只是不能在bash变量中存储零字节。不可能。
通常的解决方案是将字节流转换为十六进制。然后,在每次您想对其进行操作时将其转换回。
$ x=$(printf "ALICE\0BOB\x1fCHARLIE\n" | xxd -p)
$ <<<"$x" xxd -p -r | hexdump -C
00000000 41 4c 49 43 45 00 42 4f 42 1f 43 48 41 52 4c 49 |ALICE.BOB.CHARLI|
00000010 45 0a |E.|
00000012
您也可以为此编写自己的序列化和反序列化函数。
例如,我的另一个想法是通过使用零字节作为分隔符将数据读入数组(因为其他任何字节都是有效的)。但是,这将在区分尾随零字节方面存在问题:
$ readarray -d '' arr < <(printf "ALICE\0BOB\x1fCHARLIE\n")
$ printf "%s\0" "${arr[@]}" | hexdump -C
00000000 41 4c 49 43 45 00 42 4f 42 1f 43 48 41 52 4c 49 |ALICE.BOB.CHARLI|
00000010 45 0a 00 |E..|
# ^^ additional zero byte if input doesn't contain a trailing zero byte
00000013