如何转义二进制数据以将其包含在 Bash 脚本中

如何转义二进制数据以将其包含在 Bash 脚本中

我想创建一个 bash 脚本,从外部文件读取二进制数据的“有效负载”,并输出另一个 bash 脚本,该脚本将这些数据转义并封装在字符串变量中。示例:

  • 数据文件- 源数据:需要封装的二进制数据文件
  • myencoder.sh- 主犯:一个将二进制数据转换为带有字符串变量的脚本的 bash 脚本
  • 我的有效负载- 最终结果:由以下代码生成的 bash 脚本myencoder.sh其中包含编码数据作为字符串变量。

要使用它,我需要运行myscript.sh mydata.bin mypayload.shmyscript.sh,然后它会将 mydata.bin 文件转换/转义/包装/无论什么都转换为 mypayload.sh

运行此命令后,该mypayload.sh文件将如下所示:

# Generated by myencoder.sh with data from mydata.bin
encoded_data="[...]ugly escaped string representation of the binary data found in mydata.bin[...]"

我面临的问题是如何正确编码数据,我不确定如何解决。我读到 printf "%q" 可用于转义字符串,但如何在从外部二进制文件获取的数据上调用它,我完全不知道该如何解决。

因此,欢迎任何尝试和任何建议!

附言:如果可能的话,我不想引入 bash 之外的任何依赖项。依赖 bash 4.x 功能是可以的。

备注:编码应该有利于小尺寸和编码/解码性能。

答案1

在 bash 中处理零字节非常困难。你可以这样输出零字节:

printf %c

但不能将其存储在变量中。

使用外部工具要容易得多:

xxd < mydata.bin > encoded
xxd -r < encoded > binary

答案2

这并不能完全解决您的问题;正如其他人提到的那样,在 bash 中处理输入文件中的 NULL 很困难,而且我确信 unicode 输入文件的潜力可能会导致更多的麻烦。

但是我花了一点时间思考如何printf %q在 bash 中做类似于你的建议的事情,并想出了这个快速的破解方法:

echo -n 'myvar="'
while read -r; do
  if [ ! -z "$REPLY" ]; then
    printf %q "$REPLY"
  fi
  echo -n '\n'
done
echo '"'

我确信它可能会在很多方面被破坏但也许它可能会满足你的部分好奇心。

答案3

这个答复并没有直接回答问题,因为显然在 bash 变量中包含 0 个字节是不可能的,而且显然没有办法将它们转义为可以安全地保存在 bash 变量中的字符串,而无需依赖 xxd 或 uuencode 等外部工具,而这些工具在我的脚本将运行的平台上默认不可用。

然而,这是我最终选择的解决方案,因为它最接近地解决了我的问题,即创建一个包含任意二进制数据作为有效负载的脚本,该脚本可以由包含它的脚本来处理。

我用了本文作为我的来源。基本上,该方法在脚本和二进制数据之间使用分隔符字符串,并且永远不会让 bash 解释器到达最后的二进制部分。

相关内容