Bash math

Math expansion with backticks

z=`/usr/bin/expr $z + 3`

Math expansion with double parenthesis

The use of backticks in math expansion has been superseded by double parenthesis and the let construction. Double parenthesis is preferred over the $[ ] construct which is depreciated.

z=$(($z + 3))
z=$(( z + 3))	# dereferencing is optional

$((expression)) is math expansion, not to be confused with command substitution $(command)

You may also use operations within double parentheses without assignment

n=0
(( n += 1 ))
echo $n

Math evaluation with let

let z=z+3
let z+=3
let "z += 3" # quotes allow use of spaces

let "t2 = ((a = 9, 15 / 3))" # Set "a =9" and "t2 = 15 / 3"

Integer math

Bash can do integer arithmetic in any base from two to sixty-four.

A leading '0X' or '0x' denotes hexadecimal. Otherwise, numbers take the form [base#]n, where base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used The digits greater than 9 are represented by the lowercase letters, the uppercase letters, '&' and '_', in that order. If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

echo $[16#264bf]
156863

echo $[64#123xyzXYZ__]
1189942237139820543

NOTE: $[expression] is depreciated and will be removed in future versions of bash. Use $((expression)) instead.

echo $((16#264bf))
156863

echo $((64#123xyzXYZ__))
1189942237139820543

/usr/bin/expr 8 \* 9

echo $((8 * 9))

echo " scale=4; 3.44 / 5 " | bc

echo $(/usr/bin/bc << EOF
scale = 4
a1 = (3 + 4)
b1 = (5 + 6)
a1 + b1
EOF
)

Number Base Conversions

# Convert from base 10 to base 8
printf %o 9 # --> 11
printf -v var %0 9
echo $var # --> 11

# Convert from base 10 to base 16
printf %x 65535 # --> ffff

# Convert from base 8 to base 10
echo $(( 8#11 )) # --> 9

# Convert from base 16 to base 10
echo $(( 0xffff )) # --> 65535
echo $(( 16#ffff )) # --> 65535

Octal/Decimal/Hex to Character

# Convert a base 8 number to a character
echo -e '\077' # --> ?
echo $'\077' # --> ?

# Convert a base 10 number to a character
echo -e "\0$(printf %o 65)" # --> A

echo -ne "\0$(printf %o 5)" > lownum will create a file containing the single byte 5 (00000101)

# Convert a base 16 number to a character
echo -e "\0$(printf %o $((16#41)))" # --> A
printf '\x41' # --> A
echo $'\x41' # --> A

Character to Octal/Decimal/Hex

# Convert a character to octal
printf '%o\n' "'A" --> 101
printf '%o\n' '"A' --> 101

# Convert a character to decimal
printf '%d\n' "'A" --> 65
printf '%d\n' '"A' --> 65

# Convert a character to hex
printf '%x\n' "'A" --> 41
printf '%x\n' '"A' --> 41

From thd POSIX specification of printf:
If the leading character is a single-quote or double-quote, the value shall be the numeric value in the underlying codeset of the character following the single-quote or double-quote.

Arbitrary base conversion

The easiest way to convert values in arbitrary bases is to use ksh and typeset

ksh
$ typeset -i 16 value # output in base 16
$ value=2#11111111 # input in base 2
$ echo $value
64#ff
$

Or for bases between 2 and 16 you can use /usr/bin/bc

input=$(echo "ibase=2; 1111111111111111" | bc)
echo "obase=16; $input" | bc
FFFF

Factoring

Decompose an integer into prime factors.
/usr/bin/factor 27417
27417: 3 13 19 37

Date Manipulation

To subtract 1 from a month
newmonth=$(( (month + 10) % 12 + 1 ))

Or, if you want a two digit month
newmonth=$(( (month + 10) % 12 + 101 ))
newmonth=${newmonth:1:2}


Send mail to the Webmaster

logo This site best viewed with a browser
Warning: This is a Debian centric site
Many thanks to Debra and Ian Murdock for making Debian possible
First created Dec 14, 2008 ~ Last revised March 22, 2010

Valid XHTML 1.0 Strict Valid CSS!