Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
syntax:expansion:arith [2009/02/24 07:26] 127.0.0.1 external edit |
syntax:expansion:arith [2013/01/08 15:49] (current) ormaaj |
||
---|---|---|---|
Line 7: | Line 7: | ||
</code> | </code> | ||
- | The [[syntax:arith_expr | arithmetic expression]] ''<EXPRESSION>'' is evaluated and the resulting value replaces the whole ''<nowiki>$((...))</nowiki>'' construct: | + | The [[syntax:arith_expr | arithmetic expression]] ''<EXPRESSION>'' is evaluated and expands to the result. The output of the arithmetic expansion is guaranteed to be one word and a digit in Bash. |
Please **do not use the second form ''$[ ... ]''**! It's deprecated. The preferred and standardized form is ''<nowiki>$(( ... ))</nowiki>''! | Please **do not use the second form ''$[ ... ]''**! It's deprecated. The preferred and standardized form is ''<nowiki>$(( ... ))</nowiki>''! | ||
- | <code> | + | Example |
- | read -p "Enter first operand: " first | + | <code bash> |
- | read -p "Enter second operand: " second | + | function printSum { |
- | echo "The sum is $((first + second))" | + | 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]})) | ||
+ | } | ||
</code> | </code> | ||
- | **Note** that in Bash you don't need the arithmetic expansion to simply check for a specific value of an integer, this can be done using the [[syntax:ccmd:arithmetic_eval | arithmetic evaluation compound command]]: | + | **Note** that in Bash you don't need the arithmetic expansion to check for the boolean value of an arithmetic expression. This can be done using the [[syntax:ccmd:arithmetic_eval | arithmetic evaluation compound command]]: |
- | <code> | + | <code bash> |
- | read -p "Enter a number: " | + | printf %s 'Enter a number: ' >&2 |
+ | read -r number | ||
if ((number == 1234)); then | if ((number == 1234)); then | ||
- | echo "Good guess" | + | echo 'Good guess' |
else | else | ||
- | echo "Haha... :-P" | + | echo 'Haha... :-P' |
fi | fi | ||
</code> | </code> | ||
+ | |||
+ | **Variables** used inside the arithmetic expansion, as in all arithmetic contexts, can be used with or without variable expansion: | ||
+ | |||
+ | <code 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. | ||
+ | </code> | ||
+ | |||
+ | ===== Bugs and Portability considerations ===== | ||
+ | * The original Bourne shell doesn't have arithmetic expansions. You 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 fix any code you find that's still using ''expr''. | ||
===== See also ===== | ===== See also ===== | ||
+ | * [[syntax:arith_expr | arithmetic expressions]] | ||
+ | * [[syntax:ccmd:arithmetic_eval | arithmetic evaluation compound command]] | ||
* [[syntax:expansion:intro | Introduction to expansion and substitution]] | * [[syntax:expansion:intro | Introduction to expansion and substitution]] | ||
+ | * [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04 | POSIX definition]] | ||