Invertire un numero esadecimale in bash


10

Esiste un semplice comando per invertire un numero esadecimale?

Ad esempio, dato il numero esadecimale:

030201

L'output dovrebbe essere:

010203

Usando il revcomando, ottengo quanto segue:

102030

Aggiornare

$ 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
Per favore non aggiungere la risposta alla tua domanda.
gatto

@cat Ho aggiunto la risposta perché quella che ha funzionato per me è nei commenti della risposta selezionata. Ma sto bene rimuoverlo.
Iñaki Murillo,

2
Puoi aggiungerlo come risposta facendo clic sul pulsante "Rispondi a questa domanda" sotto la casella di risposta (le risposte automatiche sono incoraggiate) e dovresti, semplicemente, non inserirlo nella domanda.
gatto

2
Il programmatore C in me vuole dire "010203" è un numero ottale, non un numero esadecimale (0x10203)
infissa

@infisso Non hai torto, ma volevo una risposta che trattasse 010203come un esadecimale, anche se non lo uso 0x
Iñaki Murillo

Risposte:


10

È possibile convertirlo in binario , invertire i byte , rimuovererev facoltativamente le nuove righe finali <2.24 e riconvertirlo:

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

utilizzando

$ 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

Questo non funziona se la stringa contiene il byte NUL, perché revtroncerà l'output in quel punto.


2
Ricevo 0102030ainvece di010203
Iñaki Murillo l'

@ l0b0 e anche a me, get0102030a
بارپابابا

2
@ IñakiMurillo nella tua revversione 2.20.1; usa questo formiatoxxd -revert -plain <<< '030201' | LC_ALL=C rev | tr -d '\n'| xxd -plain
بارپابابا

2
revprima della versione 2.24ha un nuovo bug di linea. maggiori informazioni github.com/karelzak/util-linux/commit/…
بارپابابا

1
Non funziona se la stringa esadecimale contiene il byte NUL '00'.
Sylvain Leroux,

10

Se il tuo sistema ha un revcomando.

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

Se ha 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]}}}

(come ddnell'approccio: scambiare coppie di caratteri, dividerli in un elenco di singoli caratteri ( s::), invertire l'ordine ( Oa) e unire ( 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"
)

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
Stavo per suggerire perl -F'(..)' -lane 'print reverse(@F)':)
Sundeep

1
@Sundeep, bello. Non sapevo che si potesse usare -Fcosì. (Ora posso vederlo descritto nel split()manuale).
Stéphane Chazelas,

1
per quanto ne so, -Ffondamentalmente si divide su $_... oltre all'uso di regex come -F'/"\K\|(?=")/'si può specificare anche il numero di divisioni ... come -F'/:/,$_,2'... usare ()se si deve catturare anche il separatore
Sundeep

Invece di usare paste potresti usaretr -d '\n'
AKHolland il

10

Con fold+ tac+ tr:

$ echo 030201|fold -w2|tac|tr -d "\n"
010203
  • fold - diviso ogni 2 byte
  • tac - gatto inverso
  • tr - rimuovere le nuove righe

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

Ciò ripristina ogni riga esadecimale:

  • /(..)/g crea un elenco con le partite catturate

4

(per amor di completezza)

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

1
Questo funziona se il '00' NUL byte è nell'input.
Sylvain Leroux,

0

Sulla base della risposta di Ipor Sircer https://unix.stackexchange.com/a/321867/337458 Consiglierei questo nel tuo ~/.bashrcper avere un bel comando che puoi semplicemente chiamare:

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

$> hex_inverse 030201

010203
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.