TIL: looping over hex numbers in Bash
Sometimes we need hexadecimal numbers. Sometimes we need to loop over them. And sometimes we need to do that in Bash.
We are talking about Bash, so it only takes one line to do it. For example, to
go from 8
to 0xe
(not inclusive), and print the decimal value and their hex
number:
for ((i = 8; i < $(printf %d 0xe); ++i)); do j=$(printf "%x" $i); echo -e "$i:\t $j"; done
8: 8
9: 9
10: a
11: b
12: c
13: d
Now, let’s see bit by bit what is this one-liner. The same code, in multiple lines, for educational purposes only:
for ((i = 8; i < $(printf "%d" 0xe); ++i)); do
j=$(printf "%x" $i)
echo -e "$i:\t $j"
done
The first line is a C-style for
loop. The loop variable, i
, starts from 8
and the loop goes on while i < $(printf "%d" 0xe)
is true. The loop variable
is incremented (++i
, C-style pre-increment) at the end of each iteration.
The printf "%d" 0xe
is the cool trick: it takes the string 0xe
and
generates another string using the formatter %d
. This means: print 0xe as
an integer. This way the loop starts at 8 and ends at 14 (0xe), not
inclusive. The printf
is executed using
command substitution,
so its value “replaces” the command. This is what “tricks” the for loop into
starting from 0 and ending at 13.
As the loop is not inclusive (the condition is i < 14
), the last iteration
happens with i=13
.
The second printf
does the opposite: takes the variable i
, prints as
hexadecimal (formatter %x
is for hexadecimal numbers) and “saves” it as the
variable j
. The echo
statement prints i
, the decimal value, and j
, the
corresponding hexadecimal.
All one needs when coding in Bash is one line.
And just for fun, here’s the equivalent Python code:
for i in range(0, 0xE):
print(f"{i}: {i:x}")
But why use Python when we can suffer with Bash?