Usando o awk para armazenar um número binário no arquivo de texto como uma string e depois converter para hexadecimal

3

Estou usando awk para analisar um arquivo de texto. O arquivo de texto tem quatro campos de dados de byte e aparece assim:

11110000  10100000  10110000  10010000

Eu quero ler os campos e convertê-los de binário para hexadecimal. Atualmente estou usando printf %x . Desta forma, altera 11110000 para um decimal e depois para um número hexadecimal. Isso diz que o valor de 1111000 é 0xA98760 em vez de 0xF0 .

Meu código é simples e sou novo no BASH e no Linux.

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

Como posso armazenar os campos de string como o binário que é e depois converter em Hex? Eu posso obter o número hexadecimal do terminal usando "bc < <" obase = 16; ibase = 2; $ variável "". Quando eu tento script isso eu recebo um erro de sintaxe.

    
por Jcwilli585 03.08.2015 / 23:20

4 respostas

2

awk só faz decimal, octal e hexadecimal, não binário. Você poderia usar perl :

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

Com dc e GNU tac (consulte também tail -r em alguns sistemas):

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

Com bc (supondo que seu erro de sintaxe era sobre o operador <<< zsh usado em um shell diferente de zsh ou versões recentes de bash / ksh93 / mksh / yash )

{ echo 'obase=16; ibase=2'; tr -cs 01 '[\n*]'; } < file.txt | bc
    
por 03.08.2015 / 23:36
1

É um hack deselegante, mas funciona. Declara uma função b que recebe uma representação binária de um número e retorna o valor decimal. Em seguida, depende de printf e seu% x para exibir em hexadecimal.

$ 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
    
por 03.08.2015 / 23:48
1
perl -pale '$_ = join $", map { sprintf "%X", oct "0b$_" } @F'

Resumo:

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.
    
por 28.03.2017 / 19:30
0

Se o sistema que você está almejando tiver o GNU Bash, você pode tirar proveito de seu suporte, em expressões aritméticas, para outras bases além de octal e hexadecimal. Por exemplo:

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

Ok, então, se pegarmos esses dados:

11110000  10100000  10110000  10010000

e, de alguma forma, massageie essa sintaxe e avalie-a:

$(( 2#11110000101000001011000010010000 ))

obtemos o valor

4037062800

(Sim, isso funciona em construções de 32 bits do bash; não temos um negativo.)

Podemos fazer isso de maneira muito simples:

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

O único problema é que isso é, em certa medida, eval disfarçado. Estamos interpolando a saída de algum comando, baseado no conteúdo de um arquivo, em uma expressão que, então, é avaliada. Se file for obtido de uma fonte não confiável, pode haver implicações de segurança. Por exemplo, eu não colocaria isso em um script CGI sob o Apache, onde file vem dos dados POST de um formulário enviado por usuários arbitrários da Internet.

    
por 29.03.2017 / 20:03

Tags