How to do math in shell environments (bash, zsh, ...)
- Published at
- Updated at
- Reading time
- 3min
I was kneedeep into CI/CD scripting, when I hit a wall. You can't just do simple math like adding or subtracting integers in a shell environment? How could I have not discovered this fact before?
As it turns out, simple operations like summing and subtracting two variables need some serious shell knowledge.
Here's the problem.
#!/bin/sh
a=1
b=2
c=$a+$b
echo $c # 1+2
When evaluating c
, $a
and $b
are resolved to their values (1
and 2
), but the +
is treated as a string. All three parts are strings, and now the result is 1+2
. Ufff.
After researching this problem, I learned that there are multiple ways to do math in shell environments. Let's have a look!
Let's start with my first Google result โ expr
.
#!/bin/sh
a=1
b=2
c=`expr $a + $b`
echo $c #3
Backticks and expr
worked, but Shellcheck wasn't happy about it.
Shellcheck's slogan is that it "finds bugs in your shell scripts". And this couldn't be more true. The linter is one of these invaluable tools that shows me the problems in my lousy code.
Install it in your editor now, and thank me later. ๐
I didn't spend time on "legacy backticks" and moved on quickly.
I learned that let
and declare
let you evaluate arithmetic expressions in a single line. Fancy!
#!/bin/sh
a=1
b=2
let c=a+b
declare -i d=a+b
echo $c # 3
echo $d # 3
The let
and declare
approach also worked fine, but I didn't find these one-liners good to read.
And more importantly, again, Shellcheck complained. let
isn't available in sh
shells, and there seems to be a better option in bash
.
So here's the better and final option: the winner is arithmetic expansion ($(( ))
). It's a fancy syntax to mark parts of your shell code as an arithmetic operation. In plain English, anything between the parentheses is considered math. ๐ช
#!/bin/sh
a=1
b=2
c=$((a+b))
echo $c # 3
Again, this script worked fine, but this time Shellcheck was also happy about it. Success!
Let's look at two quick arithmetic expansion facts I discovered.
Many online examples show variables with the $
character. It's optional when you want to perform an arithmetic operation.
#!/bin/sh
a=1
b=2
c=$((a+b))
d=$(($a+$b))
echo $c # 3
echo $d # 3
Also, variables that don't represent an integer are ignored in your calculations. They don't throw an error.
#!/bin/sh
a=hello
b=3
c=$((a+b))
echo $c # 3
And that's it! If you want to do math in your shell scripts, $(( ))
is your friend.
Sure, I learned how to add numbers in a shell environment today, but can I now say I know what I'm doing when writing these scripts? Absolutely not.
My Google research unveiled all these different approaches. How would I have known what's best? I'd have used the first solution that worked. Luckily, Shellcheck showed me the way.
So there's another hidden lesson here today: linters are great software. Use them!
Join 5.5k readers and learn something new every week with Web Weekly.