Invierte un número hexadecimal en bash

10

¿Hay un comando simple para revertir un número hexadecimal?

Por ejemplo, dado el número hexadecimal:

030201

La salida debe ser:

010203

Usando el revcomando, obtengo lo siguiente:

102030

Actualizar

$ 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
Iñaki Murillo
fuente
2
Por favor no agregue la respuesta a su pregunta.
gato
@cat Agregué la respuesta porque la que funcionó para mí está en los comentarios de la respuesta seleccionada. Pero estoy bien quitándolo.
Iñaki Murillo
2
Puede agregarlo como respuesta haciendo clic en el botón "Responder a esta pregunta" debajo del cuadro de respuesta (se alientan las auto-respuestas), y debería, simplemente no lo ponga en la pregunta.
gato
2
El programador C que hay en mí quiere decir "010203" es un número octal, no un número hexadecimal (0x10203)
infijo del
@infixed No estás equivocado, pero quería una respuesta que se tratara 010203como un hexadecimal, aunque no la uso 0x
Iñaki Murillo

Respuestas:

10

Puede convertirlo a binario , revertir los bytes , opcionalmente eliminar las nuevas líneas finales rev<2.24 y volver a convertirlo:

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

Utilizando

$ 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

Esto no funciona si la cadena contiene el byte NUL, porque revtruncará la salida en ese punto.

l0b0
fuente
2
Me sale en 0102030alugar de010203
Iñaki Murillo
@ l0b0 y yo también, obtener0102030a
بارپابابا
2
@ IñakiMurillo en tu revversión 2.20.1; use este formatoxxd -revert -plain <<< '030201' | LC_ALL=C rev | tr -d '\n'| xxd -plain
بارپابابا
2
revantes de la versión 2.24tiene un nuevo error de línea. más información github.com/karelzak/util-linux/commit/…
بارپابابا
1
No funciona si la cadena hexadecimal contiene el byte NUL '00'.
Sylvain Leroux
10

Si su sistema tiene un revcomando.

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

Si tiene un comando taco tail -r:

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

Con zsh:

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

(como en el ddenfoque: intercambiar pares de caracteres, dividirlos en una lista de caracteres individuales ( s::), invertir el orden ( Oa) y unir ( j::)).

POSIXY:

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"
)

O

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

Con perl:

new_hex=$(perl -le 'print reverse(shift =~ /../g)' -- "$hex")
Stéphane Chazelas
fuente
3
Iba a sugerir perl -F'(..)' -lane 'print reverse(@F)':)
Sundeep
1
@Sundeep, bien. No sabía que se pudiera usar -Fasí. (Puedo verlo descrito en el split()manual ahora).
Stéphane Chazelas
1
por lo que sé, -Fbásicamente se está dividiendo $_... además de usar expresiones regulares como si -F'/"\K\|(?=")/'se pudiera especificar el número de divisiones también ... como -F'/:/,$_,2'... usar ()si el separador también debe ser capturado
Sundeep
En lugar de utilizar pasta se puede utilizartr -d '\n'
AKHolland
10

Con fold+ tac+ tr:

$ echo 030201|fold -w2|tac|tr -d "\n"
010203
  • fold - dividir cada 2 bytes
  • tac - gato inverso
  • tr - eliminar nuevas líneas
Ipor Sircer
fuente
4
perl -nE 'say reverse /(..)/g'

Esto revierte cada línea hexadecimal:

  • /(..)/g construye una lista con las coincidencias capturadas
JJoao
fuente
4

(en aras de la exhaustividad)

$ echo 030201 | grep -o .. | tac | paste -sd '' -
010203
zepelín
fuente
1
Esto funciona si el byte '00' NUL está en la entrada.
Sylvain Leroux
0

Basado en la respuesta de Ipor Sircer https://unix.stackexchange.com/a/321867/337458 Recomendaría esto en su ~/.bashrcpara tener un buen comando que simplemente puede llamar:

function hex_inverse() {
    echo ${1} | fold -w2 | tac | tr -d "\n" ; echo "" 
}

$> hex_inverse 030201

010203
mschmoock
fuente