shell脚本处理二进制数据
正确处理二进制数据
正确处理二进制数据必须保证以下三个环节是二进制安全(Binary Safe)的:
- 从文件读取至内存;
- 处理数据过程中;
- 内存写入至文件。
那么二进制安全是什么?通俗来说就是不会特殊处理任何数据,例如说一个文件的字节序列为(十六进制表示)0x0a 0x0d
,它读取至内存中也应该是0x0a 0x0d
不发生任何变化。
存储与读取
shell脚本只有字符串和数值两种数据类型,显而易见存储二进制应该用数值类型变量,因为字符串变量在处理过程中可能会发生转义等二进制不安全的情况。
数据类型确定了,那么如何读取文件至内存。用od(Octal Dump)命令即可,此命令用于将文件内容以特定格式输出,以下例子将foo文件中每个字节以十进制无符号整数序列方式输出,且每行最大1024个字节。
od -An -v -t u1 -w1024 ./foo
稍微处理下输出将其封装成fread函数,data变量就得到一个数值类型的数组。
function fread() {
od -An -v -t u1 -w1 "${1}"|awk -F ' ' '{printf $1" "}'
}
data=( $(fread "./demo") )
写入文件
得到数值类型的数组后其处理无特别之处,这里不做展开介绍,主要是处理之后写入文件操作。
写入操作需要借助转义(escape)符号,例如的输出单个字节(十六进制表示为ff的数值)至文件。
printf '\xff' > output
上面知道数值数组是以十进制形式存储的,所以需要先转换成十六进制,例子如下:
val=255
printf '\x'"$(printf "%x" "${val}")" > output
因此遍历待输出的数组,将每个字节通过上述方式输出至文件即可完成写入文件操作。