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

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.


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

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

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

Esto revierte cada línea hexadecimal:

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

4

(en aras de la exhaustividad)

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

1
Esto funciona si el byte '00' NUL está en la entrada.
Sylvain Leroux

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.