将特殊字符从stdin捕获到shell变量中

问题描述 投票:1回答:1

我有一个程序可以打印包含空字节\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 special-characters stdout stdin
1个回答
0
投票

您只是不能在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
© www.soinside.com 2019 - 2024. All rights reserved.