如何从shell中的二进制文件中打印浮点值?

时间:2016-04-22 10:43:04

标签: shell command-line floating-point binary-data xxd

我的二进制文件包含双浮点数(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)或广泛使用的外部工具(例如xxddcbcod,{{1等等。)。

例如,要打印十进制值,我可以使用hexdump(Vim的一部分),例如在巴什:

  • 获取第一个字节的值:

    xxd

    对于第二个和第四个字节,增加$ echo $((16#$(xxd -ps -s0 -l1 file.bin))) 176

  • 从所有8个字节中获取十进制值:

    -s

但是我想在Unix系列上打印原始浮动值($ echo $((16#$(xxd -ps -s0 -l8 file.bin))) -5732404399725297857 )。 理想情况下使用一些单行(为了使其简单作为脚本的一部分),所以我可以将其分配到文本变量或在屏幕上打印值。

我尝试使用0.123(在4字节的浮点数上使其更简单),但它没有按预期工作:

printf

根据此on-line converter$ 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实际给出的内容。)

4 个答案:

答案 0 :(得分:9)

这不使用 Python ,是一种广泛使用的外部工具, Perl

perl -e "print pack('d>',0.123)" > file.bin

perl -e "print unpack('d>',<>)" < file.bin
0.123

或者您可以使用GNU od实用程序,例如:

od -tfD file.bin
0000000                    0.123
0000010

其中-t参数指定浮点数(f)的输出格式,后跟可选的大小说明符(F表示浮点数,D表示double或{{ 1}} for long double),简而言之L可以替换为-tfD-e。要仅打印不带地址的值,可以指定-F

答案 1 :(得分:3)

od -f <filename>

这会将您的文件转储为浮点数。

od是一个标准的Linux工具,它就是我使用的工具。该联机帮助页为:

  

od - 以八进制和其他格式转储文件

答案 2 :(得分:1)

作为一个班轮

echo -n "000000000000f03f" | while read -N2 code; do printf "\x$code"; done | od -t f8

答案 3 :(得分:-2)

您可能希望考虑一些提到的工具,例如bc,它们可用于算术运算和比较 - 例如:

#!/bin/bash
A=1.3141592653581 # variable 1
B=1.3141592653589 # variable 2
if (( `echo $A"<"$B | bc` )) ; then printf "$A is: < $B\n" ; else printf "$B is: < $A\n" ; fi ;
C=$(echo "$A+$B" | bc)
printf "C == $C\n" ;

可能需要对相关数字和类型(如零)进行其他格式化;正如其他一些帖子所述,例如: How to show zero before decimal point in bc?