BASH base conversion from decimal to hex

128,632

Solution 1

With bash (or any shell, provided the printf command is available (a standard POSIX command often built in the shells)):

printf '%x\n' 85

​​​​​​​​​​​​​​​​​ With zsh, you can also do:

dec=85
hex=$(([##16]dec))

That works for bases from 2 to 36 (with 0-9a-z case insensitive as the digits).

$(([#16]dev)) (with only one #) expands to 16#55 or 0x55 (as a special case for base 16) if the cbases option is enabled (also applies to base 8 (0125 instead of 8#125) if the octalzeroes option is also enabled).

With ksh93, you can use:

dec=85
base54=${ printf %..54 "$dec"; }

Which works for bases from 2 to 64 (with 0-9a-zA-Z@_ as the digits).

With ksh and zsh, there's also:

$ typeset -i34 x=123; echo "$x"
34#3l

Though that's limited to bases up to 36 in ksh88, zsh and pdksh and 64 in ksh93.

Note that all those are limited to the size of the long integers on your system (int's with some shells). For anything bigger, you can use bc or dc.

$ echo 'obase=16; 9999999999999999999999' | bc
21E19E0C9BAB23FFFFF
$ echo '16o 9999999999999999999999 p' | dc
21E19E0C9BAB23FFFFF

With supported bases ranging from 2 to some number required by POSIX to be at least as high as 99. For bases greater than 16, digits greater than 9 are represented as space-separated 0-padded decimal numbers.

$ echo 'obase=30; 123456' | bc
 04 17 05 06

Or same with dc (bc used to be (and still is on some systems) a wrapper around dc):

$ echo 30o123456p | dc
 04 17 05 06

Solution 2

Use printf:

$ printf "%d %x\n" $((16#55)) $((10#85))
85 55

To assign the value to a variable use command substitution:

$ x=$( printf "%x" 85 ) ; echo $x
55

Solution 3

Use the built-in Arithmetic Expansion substitution present in all POSIX compliant shells - which is pretty much universal these days.

$ echo $((0xbc))
188

and

$ hex=dead
$ dec=$((0x$hex))
$ echo $dec
57005

CAUTION: Particularly in the last example the expansion could cause unexpected results - the hex digits in the variable 'hex' have to form a legal hex constant, otherwise potentially obscure error messages happen. e.g. if 'hex' were '0xdead', the arithmetic expansion would become 0x0xdead, which is not interpretable as a constant. Of course, in that case the arithmetic expansion $(($hex)) would do the trick. It is left as an exercise for the reader to create the simple substring processing pattern matching that would remove an optional '0x' prefix.

Share:
128,632

Related videos on Youtube

Dave Rove
Author by

Dave Rove

Updated on September 18, 2022

Comments

  • Dave Rove
    Dave Rove over 1 year

    In Bash, how does one do base conversion from decimal to another base, especially hex. It seems easy to go the other way:

    $ echo $((16#55))
    85
    

    With a web-search, I found a script that does the maths and character manipulation to do the conversion, and I could use that as a function, but I'd have thought that bash would already have a built-in base conversion -- does it?

  • Dave Rove
    Dave Rove about 9 years
    Thanks. Exactly what I was looking for. (And embarrassingly simple.)
  • Angel Todorov
    Angel Todorov about 9 years
    Or, use the -v option for the builtin printf: printf -v foo "%d" $((16#BEEF)); echo $foo
  • Janis
    Janis about 9 years
    @Glenn Using non-standard options (like -v) is unnecessary here; I'd avoid it.
  • Angel Todorov
    Angel Todorov about 9 years
    @StéphaneChazelas, wait a minute. Are you saying that ksh93 does not fork for x=$(some_builtin) ?
  • Janis
    Janis about 9 years
    @Stephane That's correct. Though, the # numeric base indicator is at least supported by all the prominent shells. And for the hex-conversion in this case it's not necessary, as shown in my answer: x=$( printf "%x" 85 )
  • Janis
    Janis about 9 years
    @Glenn, yes ksh has a lot optimization built in, that'a why it's often a magnitue faster than bash.
  • Thomas Guyot-Sionnest
    Thomas Guyot-Sionnest about 8 years
    You're doing the exact same thing the OP did in his example; he's looking for the reverse operation.
  • flarn2006
    flarn2006 over 7 years
    What if you want to do an arbitrary base like you can specify with #?
  • Stéphane Chazelas
    Stéphane Chazelas over 7 years
    @flarn2006. With bash builtins, you can input numbers in any base, but not output in any base other than 8, 10 and 16. For other bases, you'd need another shell like zsh or ksh or use bc/dc.
  • flarn2006
    flarn2006 over 7 years
    @StéphaneChazelas Really? That's kind of weird. It almost seems like they were too lazy to program in a syntax for it or something; there's no way the idea of outputting in any base didn't cross their minds if they implemented inputting.
  • mwfearnley
    mwfearnley over 4 years
    alias hex="printf '%x\n'"