To evaluate an arithmetic expression, the shell first expands variable and command substitutions inside it. For example, in echo "$(($num1+$num2))"
, the first thing that happens is that $num1
and $num2
are replaced by the variables' values. The expression becomes 2+5
. This is parsed as an arithmetic expression and evaluated to the number 7. The result of parsing and expanding "$(($num1+$num2))"
is thus 7
.
Arithmetic expressions can contain variable names. These are evaluated to the value of the variable. Thus $((num1+num2))
is the arithmetic expression num1+num2
(whereas $(($num1+$num2))
is the arithmetic expression 2+5
). In this case the result is the same.
The two expressions are different when the value of num1
or num2
isn't just a sequence of digits. For example, consider the following snippet:
a="1+2"
echo "$(($a * 4))"
echo "$((a * 4))"
In the second line, the arithmetic expression to be evaluated is 1+2 * 4
. This is parsed as 1 + (2 × 4) since multiplication has a higher precedence than addition. The fact that the plus sign came from the expansion of a variable is forgotten by the time the arithmetic evaluation takes place. The result is the number 9, so the first call to echo
prints 9
.
The behavior of the third line depends on the shell. Some shells (e.g. dash) complain that a
does not contain a valid numeric value. Other shells (e.g. ksh, bash, zsh) treat the value of a
as a subexpression which is evaluated to get the value to use in the main expression. That is, in these other shells, the value of a
is evaluated to 3
, and the arithmetic expression calculates 3 × 4 so the result is 12.
Finally, $[…]
is a deprecated, non-standard variant of $((…))
. The expr
utility is an older way of making arithmetic calculations in shell scripts, dating back from the time when shells didn't have a built-in arithmetic syntax. expr "$num1" + "$num2"
prints 7, as does the redundant echo `expr "$num1" + "$num2"`
(you mistyped one of the quotes).