2023-07-05 11:43:35 +02:00
|
|
|
# Arithmetic expansion
|
|
|
|
|
|
|
|
$(( <EXPRESSION> ))
|
|
|
|
|
|
|
|
$[ <EXPRESSION> ]
|
|
|
|
|
2024-01-29 02:07:56 +01:00
|
|
|
The [arithmetic expression](../../syntax/arith_expr.md) `<EXPRESSION>` is
|
2023-07-05 11:43:35 +02:00
|
|
|
evaluated and expands to the result. The output of the arithmetic
|
|
|
|
expansion is guaranteed to be one word and a digit in Bash.
|
|
|
|
|
2024-03-30 19:22:45 +01:00
|
|
|
Please **do not use the second form `$[ ... ]`**! It's deprecated. The
|
2023-07-05 11:43:35 +02:00
|
|
|
preferred and standardized form is `$(( ... ))`!
|
|
|
|
|
|
|
|
Example
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
function printSum {
|
|
|
|
typeset -A args
|
|
|
|
typeset name
|
|
|
|
for name in first second; do
|
|
|
|
[[ -t 0 ]] && printf 'Enter %s positive integer: ' "$name" >&2
|
|
|
|
read -r ${BASH_VERSION+-e} "args[$name]"
|
|
|
|
[[ ${args[$name]} == +([[:digit:]]) ]] || return 1 # Validation is extremely important whenever user input is used in arithmetic.
|
|
|
|
done
|
|
|
|
printf 'The sum is %d.' $((${args[first]} + ${args[second]}))
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2024-03-30 20:09:26 +01:00
|
|
|
**Note** that in Bash you don't need the arithmetic expansion to check
|
2023-07-05 11:43:35 +02:00
|
|
|
for the boolean value of an arithmetic expression. This can be done
|
|
|
|
using the [arithmetic evaluation compound
|
2024-01-29 02:07:56 +01:00
|
|
|
command](../../syntax/ccmd/arithmetic_eval.md):
|
2023-07-05 11:43:35 +02:00
|
|
|
|
|
|
|
``` bash
|
|
|
|
printf %s 'Enter a number: ' >&2
|
|
|
|
read -r number
|
|
|
|
if ((number == 1234)); then
|
|
|
|
echo 'Good guess'
|
|
|
|
else
|
|
|
|
echo 'Haha... :-P'
|
|
|
|
fi
|
|
|
|
```
|
|
|
|
|
|
|
|
**Variables** used inside the arithmetic expansion, as in all arithmetic
|
|
|
|
contexts, can be used with or without variable expansion:
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
x=1
|
|
|
|
|
|
|
|
echo $((x)) # Good.
|
|
|
|
echo $(($x)) # Ok. Avoid expansions within arithmetic. Use variables directly.
|
|
|
|
echo $(("$x")) # Error. There is no quote-removal in arithmetic contexts. It expands to $(("1")), which is an invalid arithmetic expression.
|
|
|
|
echo $((x[0])) # Good.
|
|
|
|
echo $((${x[0]})) # Ok. Nested expansion again.
|
|
|
|
echo $((${x[$((${x[!$x]}-$x))]})) # Same as above but more ridiculous.
|
|
|
|
echo $(($x[0])) # Error. This expands to $((1[0])), an invalid expression.
|
|
|
|
```
|
|
|
|
|
|
|
|
## Bugs and Portability considerations
|
|
|
|
|
2024-03-30 20:09:26 +01:00
|
|
|
- The original Bourne shell doesn't have arithmetic expansions. You
|
2023-07-05 11:43:35 +02:00
|
|
|
have to use something like `expr(1)` within backticks instead. Since
|
|
|
|
`expr` is horrible (as are backticks), and arithmetic expansion is
|
|
|
|
required by POSIX, you should not worry about this, and preferably
|
2024-03-30 19:22:45 +01:00
|
|
|
fix any code you find that's still using `expr`.
|
2023-07-05 11:43:35 +02:00
|
|
|
|
|
|
|
## See also
|
|
|
|
|
2024-01-29 02:07:56 +01:00
|
|
|
- [arithmetic expressions](../../syntax/arith_expr.md)
|
2023-07-05 11:43:35 +02:00
|
|
|
- [arithmetic evaluation compound
|
2024-01-29 02:07:56 +01:00
|
|
|
command](../../syntax/ccmd/arithmetic_eval.md)
|
2023-07-05 11:43:35 +02:00
|
|
|
- [Introduction to expansion and
|
2024-01-29 02:07:56 +01:00
|
|
|
substitution](../../syntax/expansion/intro.md)
|
2023-07-05 11:43:35 +02:00
|
|
|
- [POSIX
|
|
|
|
definition](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04)
|