I want to add two hexadecimal variables in a bash script. I want them to start as hex and end in hex, not decimal.

What I've come up with so far is a bit of a round about hack. Is there a better or more elegant solution?




NEW_BASE=`printf "0x%X\n" $NEW_BASE`

echo $NEW_BASE


5 Answers 5


I would just simplify your script as:

printf "0x%X\n" $((0xA000 + 0x1000))
  • 1
    or printf -v newbase "0x%X\n" $((0xA000 + 0x1000)); echo $newbase
    – Cyrus
    Jan 5, 2018 at 21:02
  • I like the one liner :) Any way to get rid of the subshell (back ticks) for variable assignment? Jan 5, 2018 at 21:03
  • 1
    Thers's no subshell. $((...)) is ugly addition syntax. With bash this is also possible: $[0xA000 + 0x1000]
    – Cyrus
    Jan 5, 2018 at 21:04
  • @Cyrus It is possible, but it is a deprecated format. Jan 5, 2018 at 21:07
  • 1
    I need the final result assigned to a variable though. Hence the subshell with the printf wrapped in back ticks. Still, this is the best yet :) Jan 6, 2018 at 3:50

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))
$ echo $(([##16] 0xff + 0xff))
$ echo 0x$(([##16] 0xff + 0xff))
$ echo $(([##2] 0xff + 0xff))

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
$ printf '%#..2d\n' 0x1FE

In ksh93, var=$(printf...) doesn't fork a subshell so is as efficient as bash's printf -v.

  • I wasn't aware of the -v <variable assignment syntax> NIIICE!!! Thank you :) Jan 6, 2018 at 3:55

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).


within bash it seems to be the good method. you can also call tools like bc/dc (depending on your preferences) ... echo 'obase=30; 123456' | bc

but I prefer the bash method In my point of view you 're doing well

  • Thank you :) But that shell to printf is what makes me twitch. Would be nice to not need to subshell out to get a formatted result. Jan 5, 2018 at 20:52
  • 1
    @DavidAubin Note that printf is a bash built-in and probably much faster that any real command like bc.
    – rudimeier
    Jan 5, 2018 at 21:03

The sum of $hexNumA and $hexNumB is:

printf "%x\n" $((16#$hexNumA + 16#$hexNumB))

You can even add decimal to hex just as easily:

printf "%x\n" $((16#$hexNum + $decNum))

courtesy: "Convert Hexadecimal to Decimal in Bash"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.