Odwróć liczbę szesnastkową w bash


10

Czy istnieje proste polecenie odwrócenia liczby szesnastkowej?

Na przykład, biorąc pod uwagę liczbę szesnastkową:

030201

Dane wyjściowe powinny być:

010203

Za pomocą revpolecenia otrzymuję:

102030

Aktualizacja

$ 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
Nie dodawaj odpowiedzi do swojego pytania.
kot

@cat Dodałem odpowiedź, ponieważ ta, która działała dla mnie, jest na komentarzach do wybranej odpowiedzi. Ale mogę to usunąć.
Iñaki Murillo,

2
Możesz dodać ją jako odpowiedź, klikając przycisk „Odpowiedz na to pytanie” pod polem odpowiedzi (zachęcamy do samodzielnego udzielania odpowiedzi), i powinieneś po prostu nie umieszczać jej w pytaniu.
kot

2
Programista C we mnie chce powiedzieć „010203” to liczba ósemkowa, a nie liczba hex (0x10203)
infixed

@infixed Nie mylisz się, ale chciałem odpowiedzi, która traktuje 010203jako szesnastkową, mimo że nie używam 0x
Iñaki Murillo

Odpowiedzi:


11

Możesz przekonwertować go na binarny , odwrócić bajty , opcjonalnie usunąć końcowe znaki nowej linii rev<2.24 i przekonwertować z powrotem:

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

Za pomocą

$ 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

Nie działa to, jeśli ciąg zawiera bajt NUL, ponieważ revw tym momencie obcina dane wyjściowe.


2
Dostaję 0102030azamiast010203
Iñaki Murillo

@ l0b0 i ja też, weź0102030a
Baba

2
@ IñakiMurillo w twojej revwersji 2.20.1; użyj tego mrówczanuxxd -revert -plain <<< '030201' | LC_ALL=C rev | tr -d '\n'| xxd -plain
Baba

2
revprzed wersją 2.24mają nowy błąd linii. więcej informacji github.com/karelzak/util-linux/commit/…
Baba

1
Nie działa, jeśli ciąg szesnastkowy zawiera bajt NUL „00”.
Sylvain Leroux,

10

Jeśli twój system ma revpolecenie.

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

Jeśli ma polecenie taclub tail -r:

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

Z zsh:

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

(jak w ddpodejściu: zamień pary znaków, podziel na listę pojedynczych znaków ( s::), odwróć kolejność ( Oa) i łączyć ( 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"
)

Lub

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

Z perl:

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

3
Chciałem zasugerować perl -F'(..)' -lane 'print reverse(@F)':)
Sundeep

1
@ Sundeep, miło. Nie wiedziałem, że można -Ftak używać . (Widzę to teraz opisane w split()instrukcji).
Stéphane Chazelas

1
o ile wiem, -Fto w zasadzie podział na $_... oprócz użycia wyrażenia regularnego, tak jak -F'/"\K\|(?=")/'można określić liczbę podziałów, jak również ... na przykład -F'/:/,$_,2'... użyj, ()jeśli separator również musi zostać przechwycony
Sundeep

Zamiast używać pasty możesz użyćtr -d '\n'
AKHolland

10

Z fold+ tac+ tr:

$ echo 030201|fold -w2|tac|tr -d "\n"
010203
  • fold - dzielone co 2 bajty
  • tac - rewers kat
  • tr - usuń nowe linie

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

Spowoduje to cofnięcie każdej linii szesnastkowej:

  • /(..)/g buduje listę przechwyconych dopasowań

4

(ze względu na kompletność)

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

1
To działa, gdy „00” NUL bajt znajduje się w wejściu.
Sylvain Leroux,

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.