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

vktxenjb  于 2023-05-01  发布在  Shell
关注(0)|答案(5)|浏览(123)

我有二进制文件组成的双浮点数(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)。
如何使用更干净的方式(不使用Python)从shell脚本打印该值?使用内置工具(例如例如printf),或广泛使用的外部工具(例如例如xxddcbcodhexdump等。).
例如,要打印十进制值,我可以使用xxd(Vim的一部分),e。在Bash中:

  • 获取第一个字节的值:
$ echo $((16#$(xxd -ps -s0 -l1 file.bin)))
176

对于第2个和第4个字节,增加-s

  • 从所有8个字节中获取十进制值:
$ 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

根据这个on-line converter0x3dfbe76d0.123相同,所以十六进制值是相反的(xxd实际给出的)。

ulmd4ohb

ulmd4ohb1#

它不使用Python,而是广泛使用的外部工具Perl

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

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

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

od -tfD file.bin
0000000                    0.123
0000010

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

7hiiyaii

7hiiyaii2#

od -f <filename>

它将把你的文件转储为浮动。
od是一个标准的Linux工具,我也使用它。手册页内容如下:
od -八进制和其他格式的转储文件

jei2mxaa

jei2mxaa3#

作为一个oneliner

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

yzckvree4#

od -tfD filename可以完成这项工作。在此处检查od后面的特定标志:https://www.ibm.com/docs/en/zos/2.4.0?topic=descriptions-od-dump-file-in-specified-format

p1tboqfb

p1tboqfb5#

您可能希望考虑一些提到的工具,如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?

相关问题