Reverse a hexadecimal number in bash
You can convert it to binary, reverse the bytes, optionally remove trailing newlines rev
<2.24, and convert it back:
$ xxd -revert -plain <<< 030201 | LC_ALL=C rev | tr -d '\n' | xxd -plain
010203
Using
$ 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
This does not work if the string contains the NUL byte, because rev
will truncate the output at that point.
If your system has a rev
command.
hex=030201
new_hex=$(printf %s "$hex" | dd conv=swab 2> /dev/null | rev)
If it has a tac
or tail -r
command:
new_hex=$(echo "$hex" | fold -w 2 | tac | paste -sd '\0' -)
With zsh
:
setopt extendedglob
new_hex=${(j::)${(s::Oa)${hex//(#b)(?)(?)/$match[2]$match[1]}}}
(like in the dd
approach: swap pairs of characters, split into list of individual characters (s::
), reverse the order (Oa
) and join (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"
)
Or
new_hex=$(echo "$hex" |
sed -e 'G;:1' -e 's/\(..\)\(.*\n\)/\2\1/;t1' -e 's/.//')
With perl
:
new_hex=$(perl -le 'print reverse(shift =~ /../g)' -- "$hex")
With fold
+ tac
+ tr
:
$ echo 030201|fold -w2|tac|tr -d "\n"
010203
fold
- split every 2 bytetac
- reverse cattr
- remove newlines