简短的:

简短的:

我用来awk解析文本文件。该文本文件有四个字节数据字段,如下所示:

11110000  10100000  10110000  10010000

我想读取这些字段并将它们从二进制转换为十六进制。目前我正在使用printf %x.这样就变成11110000了十进制数,然后变成了十六进制数。这表示 的值11110000xA98760而不是0xF0

我的代码很简单,而且我对 BASH 和 Linux 很陌生。

awk'{printf(%x %x %x %x, $1, $2, $3, $4)};

如何将字符串字段存储为二进制文件,然后转换为十六进制?我可以使用“ bc <<<”obase=16;ibase=2; 从终端获取十六进制数字。 $变量""。当我尝试编写此脚本时,出现语法错误。

答案1

awk只支持十进制、八进制和十六进制,不支持二进制。你可以使用perl

perl -lane 'BEGIN{$, = " "} print unpack "(H2)*", pack("(B8)4", @F)'

对于dcGNU tac(另请参阅tail -r某些系统):

{ echo 16o2i; cat; echo f; } < file.txt | dc | tac

使用(假设您的语法错误与在 shell 中使用的运算符bc有关,而不是最新版本的// / )<<< zshzshbashksh93mkshyash

{ echo 'obase=16; ibase=2'; tr -cs 01 '[\n*]'; } < file.txt | bc

答案2

这是一个不优雅的黑客,但它确实有效。声明一个函数 b,它采用数字的二进制表示形式并返回十进制值。然后依靠printf它的 %x 以十六进制显示。

$ awk 'func b(i, t,a,c){a=1;for(c=length(i);c>0;c--){t+=substr(i,c,1)=="1"?a:0;a*=2}return t}{printf "0x%x 0x%x 0x%x 0x%x\n",b($1),b($2),b($3),b($4)}' bin.txt
0xf0 0xa0 0xb0 0x90

答案3

perl -pale '$_ = join $", map { sprintf "%X", oct "0b$_" } @F'

简短的:

Perl options:
     -p => autoprint + implcit file read in/line, a.la., awk
     -a => autosplit line into fields using default delimiter ' '
     -l => ORS=IRS="\n"

Perl standard variables:
      $" => list separator, by default it is a single space " "
      $_ => refers to the whole line, equivalent to $0 in awk
      @F => fields got by splitting the current line, $1, $2,$3, ... $NF in awk

Perl code:
      map { body } list_of_items
           Map takes in an input list and applies the code present in 
           it's body on each element of this list to generate an output list.
      join <separator>, <list>
           Join takes in an input list and joins their elements by the 
           separator provided in the first argument.

       oct <number>
            When the input to this function is prefixed by a "0b", then
            it is treated to be a binary number and outputs the decimal
            equivalent.

       sprintf "%x" <decimal>
             This function whose format is "%x" treats the input as
             decimal and returns the equivalent number in hex.

答案4

如果您的目标系统具有 GNU Bash,您可以利用其算术表达式中对八进制和十六进制以外的基数的支持。例如:

bash$ echo $(( 2#1011 | 2#1100 ))   # bitwise OR of 11 and 12
15

好的,如果我们获取这些数据:

11110000  10100000  10110000  10010000

并以某种方式将其融入此语法并对其进行评估:

$(( 2#11110000101000001011000010010000 ))

我们得到了值

4037062800

(是的,这适用于 32 位 bash 版本;我们没有得到否定结果。)

我们可以非常简单地做到这一点:

echo $(( 2#$(tr -d ' ' < file) ))
4037062800

唯一的问题是,这在某种程度上是eval伪装的。我们根据文件的内容将某个命令的输出插入到一个表达式中,然后对其进行求值。如果file从不受信任的来源获得,可能会存在安全隐患。例如,我不会将其放入 Apache 下的 CGI 脚本中,其中file包含任意 Internet 用户提交的表单的 POST 数据。

相关内容