How to add two hexadecimal numbers in a bash script
I would just simplify your script as:
printf "0x%X\n" $((0xA000 + 0x1000))
Yes, in bash
, printf
is the only builtin way to reformat a number in a different base and only bases 8, 10 and 16 are supported.
In bash
(contrary to shells like ksh93
or fish
), using command substitution implies forking a subshell. You can use printf -v
here to avoid the subshell (also available in recent versions of zsh
for print
and printf
(print -f
) which also supports printing into arrays):
printf -v NEWBASE '%#X' "$((BASE + OFFSET))"
(in bash
, contrary to zsh
, $((...))
is subject to word splitting, so needs quoted to avoid the dependency on $IFS
).
In zsh
, you can specify the expansion base as part of the arithmetic expansion syntax (bases 2 to 36):
$ echo $(([#16] 0xff + 0xff))
16#1FE
$ echo $(([##16] 0xff + 0xff))
1FE
$ echo 0x$(([##16] 0xff + 0xff))
0x1FE
$ echo $(([##2] 0xff + 0xff))
111111110
With ksh and zsh, you can also force the expansion of an integer variable to be in a specific base with:
typeset -i 16 NEWBASE
The expansion will be in the 16#1FE
form. ksh93 supports bases up to 64, zsh
and mksh
up to 36.
ksh93's printf
builtin supports outputting number in arbitrary bases as well with or without the n#
prefix:
$ printf '%..2d\n' 0x1FE
111111110
$ printf '%#..2d\n' 0x1FE
2#111111110
In ksh93, var=$(printf...)
doesn't fork a subshell so is as efficient as bash
's printf -v
.
In GNU or modern BSD dc
you can do this like so:
echo A000 1000 | dc -e '16o16i?+p'
16o
sets the output base. 16i
sets the input base. The ?
reads in a line from standard input, which in this case pushes two numbers onto the stack. +
adds them. p
prints the top of the stack (the answer).