我有一个二进制文件,其中包含双精度浮点数(8个字节)或单精度浮点数(4个字节)的值,该文件是以下方式生成的:
$ python -c $'from struct import pack\nwith open("file.bin", "wb") as f: f.write(pack("<d", 0.123))'
$ xxd file.bin
00000000: b072 6891 ed7c bf3f .rh..|.?
我可以通过Python打印回来:
$ python -c $'from struct import unpack\nwith open("file.bin", "rb") as f: print(unpack("<d", f.read(8)))'
(0.123,)
对于4字节浮点数,只需将
<d
更改为<f
(稍后称为float.bin
)。如何以更清晰的方式从shell脚本中打印该值(不使用Python)?可以使用内置工具(例如
printf
)或广泛使用的外部工具(例如xxd
、dc
、bc
、od
、hexdump
等)。
例如,要打印十进制值,我可以使用
xxd
(Vim的一部分),例如在Bash中:
get the value of first byte:
$ echo $((16#$(xxd -ps -s0 -l1 file.bin))) 176
For 2nd and forth bytes, increase
-s
.get decimal value from all 8 bytes:
$ echo $((16#$(xxd -ps -s0 -l8 file.bin))) -5732404399725297857
然而,我希望在Unix系统上打印原始浮点值(0.123
)。最好使用一些单行代码(作为脚本的一部分保持简单),这样我可以将其分配到文本变量中或将该值打印在屏幕上。
我尝试使用printf
(对4字节浮点数进行简化),但结果与预期不符:
$ xxd -p float.bin
6de7fb3d
$ printf "%.4f\n" 0x.$(xxd -p float.bin)
0.4293
$ printf "%.4f\n" 0x3dfbe76d
1039918957.0000
$ printf "%.4e\n" 0x3dfbe76d
1.0399e+09
根据此 在线转换器,
0x3dfbe76d
等同于 0.123
,所以十六进制值是反向的(实际上是由 xxd
给出的)。
coreutils
的一部分od
更短,这个方法效果很好,谢谢。这是精简版本:od -tfD file.bin | awk '{print $2}' | xargs
。 - kenorb