What is nice about shell scripting on Linux is that the language is just as complete as most of the compiled languages. What elements makes up a pretty good computer language.
- variables
- assignments
- conditionals
- statements
- flow control
- expressions
- functions
These elements are used in all computer languages from Lisp to C, and they all exist in bash script as well. Some of these elements also exist in windows batch files but not all. In Windows functions are a bit rudimentary and there is no math.
There are a few ways to implement math in bash scripts. One of the methods that used to be used a long time ago is the external expr command. This command will evaluate integer expressions. The easiest way to see what this command can do is to try it on the command prompt.
> expr 3 \* 3
9
The reason for the backslash is because we need to escape the asterisk from the shell. We need to do that for any character that could be interpreted by the shell. If you are using parenthesis then this has a tendency to make equations look pretty horrible.
> expr \( 3 \* 4 \) / 2
6
Even if you can stand to look at your equations like this, you do have to be careful to include spaces between each element, failure to do so will yield the ever so helpful syntax error message.
There is really no reason to use this command any longer as there are easier ways to do it in shell itself. The shell offers a easy syntax which allows you to enter the equation in a much more natural way. Simply enclose your equation with inside of a pair of parenthesis.
$(( expression goes here ))
> echo $(( 5 * 17 / 7 ))
12
Not only is this easier to read, requires less care with respect to spaces but is also faster. It is faster as the overhead of external command is no longer necessary.
Unfortunately there is a small drawback for both of these methods of evaluating expressions – they only support integer math.
In those cases where you really need floating point math you will have to use an external program. The easiest choice is to use bc. It is possible set the number of decimal places using the scale variable.
echo $(echo "scale=4; 1 / 9 " | bc )
.1111
This actually does the trick and if you are looking a specific number of decimal places this is perfect. If you are not looking for a specific number of decimal places, it is easier to use the “-l” option in conjunction with bc. This will load the mathlib but more important it will set the number of decimal places to 20.
echo 1 / 9 | bc -l
.11111111111111111111
This is actually really easy to do simple equations but unfortunately it is not possible to use any functions in your equation. This makes sense as the functions are local to the shell while bc is an external program.