Binary to hexadecimal and decimal in a shell script
Solution 1
It's fairly straightforward to do the conversion from binary in pure bash (echo
and printf
are builtins):
Binary to decimal
$ echo "$((2#101010101))"
341
Binary to hexadecimal
$ printf '%x\n' "$((2#101010101))"
155
Going back to binary using bash alone is somewhat more complex, so I suggest you see the other answers for solutions to that.
Solution 2
Assuming that by binary, you mean binary data as in data with any possible byte value including 0, and not base-2 numbers:
To convert from binary, od
(standard), xxd
(comes with vim
) or perl
's unpack
come to mind.
od -An -vtu1 # for decimal
od -An -vtx1 # for hexadecimal
xxd -p # for hexa
perl -pe 'BEGIN{$\="\n";$/=\30};$_=unpack("H*",$_)' # like xxd -p
# for decimal:
perl -ne 'BEGIN{$\="\n";$/=\30;$,=" "}; print unpack("C*",$_)'
Now, to convert back to binary, awk
(standard), xxd -r
or perl
's pack
:
From the decimal output from od -tu1
or perl
above:
LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'
From the hexa perl
or xxd -p
above:
xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'
Solution 3
You can use bc for this by manipulating the ibase
and obase
parameters:
The trick is that you need to be explicit about the bases. So if your ibase is 2, then if you set your obase to 10, it won't do anything, as 10 in binary is 2. Hence you need to use hexadecimal notation.
So binary to decimal would be (watch that obase is A)
Binary to decimal:
$> echo 'ibase=2;obase=A;11110001011010'|bc
15450
Binary to hex:
$> echo 'ibase=2;obase=10000;11110001011010'|bc
3C5A
If the 'output base' obase
is changed first, it should be easier:
$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A
Solution 4
If you mean converting numbers from base-2 to 10 or 16 and back, bc
is the standard tool to do that as already mentioned by psarossy.
decimal=123
binary=$(echo "obase=2;$decimal" | bc)
hex=$(echo "obase=16;ibase=2;$binary" | bc)
Some shells like zsh
have builtin support for base conversion as part of their arithmetic expansion operators:
decimal=123
binary=$(([##2]decimal))
hex=$(([##16]decimal))
hex=$(([##16]2#$binary))
decimal=$((2#$binary))
and so on.
Both ksh93
and zsh
also support:
typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'
But note that, when expanded, $binary
will have a 2#
or 16#
prefix (which you can strip with ${binary#*#}
.
ksh93
also supports:
printf "%..2d\n" 123
to convert to binary.
Solution 5
As mentioned in previous answer you can do Binary to Decimal and Hexa Decimal as follows in Bash using echo and printf. I am just adding here how to convert from Decimal and Hex to binary using pure Bash.
Binary to Decimal using echo
echo "$((2#101010101))"
341
Binary to Hexa-Decimal using printf
printf '%x\n' "$((2#101010101))"
155
Integer decimal to Binary conversion using only Bash
Using only Bash, if you would like to convert decimal to binary, you can do it like the following:
touch dec2bin && chmod +x "$_" && vim "$_"
And then copy and paste the following:
#!/bin/bash
## converting decimal integer to binary, pass int as a parameter
num=$1;
dec2bin()
{ [ "$num" == "" ] && { printf "Error: Pass an integer\n"; exit 1; };
op=2; ## Since we're converting to binary
quo=$(( $num / $op)); rem=$(( $num % $op)); ## quotient and remainder
remarray=(); ## array for putting remainder inside array
remarray+=("$rem"); ## array expansion
until [[ $quo -eq 0 ]]; do
num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
done
binary=$(echo "${remarray[@]}" | rev); ## reversing array
printf "$binary\n"; ## printing reversed array
}
main()
{ [[ -n ${num//[0-9]/} ]] &&
{ printf "Error: $num is not an integer bruv!\n"; return 1;
} || { dec2bin $num; }
}
main;
And then try it from where you saved:
./dec2bin 420
110100100
Integer must be added!!
./dec2bin 420.py
420.py is not an integer bruv!
Hexadecimal to Binary conversion using only Bash
Similarly, hexadecimal to binary, as follows using only bash:
#!/usr/local/bin/bash
## converting hexadecimal to binary, pass hex as a parameter
hex=$1;
hex2bin()
{ [ "$hex" == "" ] && { printf "Error: Pass a hex\n"; exit 1; };
op=2; num=$((16#$hex)); ## converting hex to integer
quo=$(( $num/ $op)); rem=$(( $num% $op)); ## quotient and remainder
remarray=(); remarray+=("$rem"); ## array expansion
until [[ $quo -eq 0 ]]; do
num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
done
binary=$(echo "${remarray[@]}" | rev); ## reversing array
printf "$binary\n"; ## printing reversed array
}
main()
{
[[ -n ${hex//[0-9,A-F,a-f]/} ]] &&
{ printf "Error: $hex is not a hex bruv!\n"; return 1;
} || { hex2bin $hex; }
}
main;
For example:
./hex2bin 1aF
110101111
Hex must be passed:
./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
Related videos on Youtube
Bangi
Updated on September 18, 2022Comments
-
Bangi almost 2 years
I have a context where I need to convert binary to hexadecimal and decimal and viceversa in a shell script. Can someone suggest me a tool for this?
-
goldilocks over 11 yearsThis second example is wrong -- 'F' would be base 15, not 16 (decimal 16 in hex is 10, not F). Try
echo 'ibase=2;obase=F;1111
which should equal decimal 15, ie. F in hex. It comes out as 10, which it is in base 15 (digits 0-E). It is also easier if you state the obase first, eg:echo 'obase=16;ibase=2;1111'|bc
. No confusion. -
Bangi over 11 yearshow about decimal to hexadecimal.
-
Andrea Corbellini over 11 yearsWhat's the point of using
printf %d
for bin2dec?$(( ... ))
already gives a decimal result,echo
is enough. -
clerksx over 11 years@AndreaCorbellini - Personal preference. In general, I use
printf '%s\n' foo
instead ofecho
for a variety of reasons (mostly portability), for the same reason, I don't use it here. -
Andrea Corbellini over 11 years@ChrisDown: I though this question was explicitly about Bash (which has a well-implemented
echo
builtin). My bad! -
manatwork over 11 yearsNow it is worst. Once you set
ibase
, you have to provide input in that base, even forobase
. So in your example would beecho 'ibase=2;obase=10000;11110001011010'|bc
. Better listen to goldilocks's advice and reverse the order – first setobase
, thenibase
. -
Franki over 9 yearsI don't know of any shorter way for
bash
andash
shells to convert numbers back into binary than to usebc
:printf -- 'obase=2;%d\n' "341" | bc
, however, I don't find it fast enough -
Zimba over 3 yearsxxd -r gives binary data, not ascii equivalent of hex data. ie 11111111 in binary file is FF in hex data. The question is asking to give 11111111 in ascii (displayable on screen)