Inverter um número hexadecimal no bash


10

Existe um comando simples para reverter um número hexadecimal?

Por exemplo, dado o número hexadecimal:

030201

A saída deve ser:

010203

Usando o revcomando, recebo o seguinte:

102030

Atualizar

$ bash --version | head -n1
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
$ xxd -version
xxd V1.10 27oct98 by Juergen Weigert
$ rev --version
rev from util-linux 2.20.1

2
Por favor, não adicione a resposta à sua pergunta.
gato

@cat Adicionei a resposta porque a que funcionou para mim está nos comentários da resposta selecionada. Mas estou bem em removê-lo.
Iñaki Murillo 8/16

2
Você pode adicioná-lo como resposta clicando no botão "Responder a esta pergunta" abaixo da caixa de respostas (as auto-respostas são incentivadas) e você deve, apenas não colocá-lo na pergunta.
gato

2
O programador C em mim quer dizer "010203" é um número octal, não um número hexadecimal (0x10203)
fixado em

@infixed você não está errado, mas eu queria uma resposta que trata 010203como um hexadecimal, embora eu não use 0x
Iñaki Murillo

Respostas:


10

Você pode convertê-lo em binário , reverter os bytes , opcionalmente, remover novas linhas finais rev<2.24 e convertê-lo novamente:

$ xxd -revert -plain <<< 030201 | LC_ALL=C rev | tr -d '\n' | xxd -plain
010203

Usando

$ bash --version | head -n1
GNU bash, version 4.3.42(1)-release (x86_64-redhat-linux-gnu)
$ xxd -version
xxd V1.10 27oct98 by Juergen Weigert
$ rev --version
rev from util-linux 2.28.2

Isso não funciona se a cadeia de caracteres contiver o byte NUL, porque revtruncará a saída nesse ponto.


2
Eu recebo em 0102030avez de010203
Iñaki Murillo 8/16

@ l0b0 e também eu, get0102030a
#

2
@ IñakiMurillo na sua revversão 2.20.1; use este formatoxxd -revert -plain <<< '030201' | LC_ALL=C rev | tr -d '\n'| xxd -plain
#

2
revantes da versão 2.24tem um novo erro de linha. mais informações github.com/karelzak/util-linux/commit/...
بارپابابا

1
Não funciona se a cadeia hexadecimal contiver o byte NUL '00'.
22416 Sylvain Leroux

10

Se o seu sistema possui um revcomando.

hex=030201
new_hex=$(printf %s "$hex" | dd conv=swab 2> /dev/null | rev)

Se tiver um comando tacou tail -r:

new_hex=$(echo "$hex" | fold -w 2 | tac | paste -sd '\0' -)

Com zsh:

setopt extendedglob
new_hex=${(j::)${(s::Oa)${hex//(#b)(?)(?)/$match[2]$match[1]}}}

(como na ddabordagem: troque pares de caracteres, divida na lista de caracteres individuais ( s::), inverta a ordem ( Oa) e junte-se ( j::)).

POSIXly:

new_hex=$(
  awk '
    BEGIN {
      hex = ARGV[1]; l = length(hex)
      for (i = 1; i < l; i += 2)
        new_hex = substr(hex, i, 2) new_hex
      print new_hex
    }' "$hex"
)

Ou

new_hex=$(echo "$hex" |
  sed -e 'G;:1' -e 's/\(..\)\(.*\n\)/\2\1/;t1' -e 's/.//')

Com perl:

new_hex=$(perl -le 'print reverse(shift =~ /../g)' -- "$hex")

3
Eu ia sugerir perl -F'(..)' -lane 'print reverse(@F)':)
Sundeep

1
@ Sundeep, nice. Eu não sabia que alguém poderia usar -Fassim. (Eu posso vê-lo descrito no split()manual agora).
Stéphane Chazelas 8/16

1
até onde eu sei, -Fé basicamente dividir $_... além de usar regex, como -F'/"\K\|(?=")/'se pode especificar o número de divisões também ... como -F'/:/,$_,2'... use ()se o separador precisar ser capturado também
Sundeep

Em vez de usar colar você poderia usartr -d '\n'
AKHolland

10

Com fold+ tac+ tr:

$ echo 030201|fold -w2|tac|tr -d "\n"
010203
  • fold - dividir a cada 2 bytes
  • tac - gato reverso
  • tr - remover novas linhas

4
perl -nE 'say reverse /(..)/g'

Isso reverte cada linha hexadecimal:

  • /(..)/g constrói uma lista com as correspondências capturadas

4

(por uma questão de completude)

$ echo 030201 | grep -o .. | tac | paste -sd '' -
010203

1
Isso funciona se o byte NUL '00' estiver na entrada.
Sylvain Leroux

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.