Shell通过dd、od、xxd等工具可完成轻量级二进制解析,核心是将二进制转为十六进制或字节序列后用awk/sed处理;支持按偏移提取、格式识别、结构化解析及二进制写入,但需注意编码和系统差异。

Shell本身不擅长直接处理二进制数据,但通过组合dd、od、xxd、printf和hexdump等工具,可以完成轻量级的二进制文件解析任务。关键在于把二进制内容转为可处理的文本表示(如十六进制或字节序列),再用awk、sed或纯bash做逻辑提取。
提取指定偏移处的字节或字段
用dd配合od或xxd精准读取某段原始数据:
-
dd if=file.bin bs=1 skip=12 count=4 2>/dev/null | od -An -tu1—— 跳过前12字节,读4字节,输出为无符号十进制整数(适合解析长度、标志位) -
dd if=file.bin bs=1 skip=20 count=8 2>/dev/null | xxd -p -c8—— 读8字节,以紧凑十六进制字符串输出(便于后续grep或case匹配) - 注意
bs=1确保按字节寻址;skip单位是bs块大小,不是bit
解析固定格式头部(如ELF、PNG、自定义协议)
多数二进制格式头部有确定结构(例如PNG魔数为89 50 4E 47),可用十六进制比对快速识别:
- 检查PNG文件:
head -c4 file.bin | xxd -p | grep -q "^89504e47$" && echo "valid PNG" - 解析4字节小端整数(如文件长度):
dd if=file.bin bs=1 skip=4 count=4 2>/dev/null | xxd -p -c4 | sed 's/../& /g' | awk '{print strtonum("0x"$4$3$2$1)}' - 更可靠的做法:用
od -An -tx1 -N4 file.bin | tr -d ' \n'先获取原始hex串,再用bash内置printf "%d" 0x...转换
批量提取结构化字段(如日志/传感器二进制记录)
若文件由重复的N字节记录组成(如每16字节含2字节ID + 4字节时间戳 + 10字节payload),可用循环+dd分片处理:
- 计算总记录数:
records=$(( $(stat -c%s file.bin) / 16 ))(Linux) - 逐条解析:
for i in $(seq 0 $((records-1))); do offset=$((i*16)); dd if=file.bin bs=1 skip=$offset count=2 2>/dev/null | od -An -tu2; done - 避免频繁调用
dd影响性能:用xxd -c16 -ps file.bin一次性转为每行16字节hex,再用awk按列切分
写入二进制数据(构造测试文件或补丁)
printf是shell中构造二进制内容最直接的方式,支持十六进制和转义序列:
- 写入3字节:
printf '\x48\x65\x6c' > hello.bin(对应ASCII "Hel") - 写入2字节小端整数1000:
printf '\x28\x03' > data.bin(因为1000 = 0x0328,小端即0x28 0x03) - 拼接多个部分:
{ printf '\x89\x50\x4E\x47'; cat payload.bin; } > out.png
不复杂但容易忽略:Shell脚本处理二进制时务必关闭字符编码干扰(如LC_ALL=C),避免grep或sed误判非打印字符;同时注意不同系统dd语法差异(macOS需用bs=1而非ibs=1 obs=1)。真正复杂的解析建议交给python -c临时脚本,Shell更适合胶水层调度和简单字段提取。

















