Trying to figure out how to convert an argument to an integer to perform arithmetic on, and then print it out, say for addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
In bash, one does not "convert an argument to an integer to perform arithmetic". In bash, variables are treated as integer or string depending on context.
(If you are using a variable in an integer context, then, obviously, the variable better contain a string that looks like a valid integer. Otherwise, you'll get an error.)
To perform arithmetic, you should invoke the arithmetic expansion operator $((...))
. For example:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
or generally preferred:
$ echo "$((a + 1))"
3
You should be aware that bash (as opposed to ksh93, zsh or yash) only performs integer arithmetic. If you have floating point numbers (numbers with decimals), then there are other tools to assist. For example, use bc
:
$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14
Or you can use a shell with floating point arithmetic support instead of bash:
zsh> echo $((3.14 + 1))
4.14
delcare -i
. For example, declare -i x; x=string; echo $x;
will print 0
Other way, you can use expr
Ex:
$ version="0002"
$ expr $version + 0
2
$ expr $version + 1
3
In bash
, you can perform the converting from anything to integer using printf -v:
printf -v int '%d\n' "$1" 2>/dev/null
Floating number will be converted to integer, while anything are not look like a number will be converted to 0. Exponentiation will be truncated to the number before e
Example:
$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
printf -v
this can be achieved with command substitution: int="$(printf '%d' 123.123 2>/dev/null)"
Commented
Apr 13, 2018 at 19:11
int
is undefined (that's why there's an error message that needed to be redirected to stderr, even as it appears to truncate at the decimal), so instead, just format as float with zero decimals, eg, printf '%.0f' 123.123
results in 123
without any error message. (Obviously works for integer arguments as well.)
A similar situation came up recently when developing bash scripts to run in both Linux and OSX environments. The result of one command in OSX returned a string containing the result code; i.e., " 0"
. Of course, this failed to test correctly in the following case:
if [[ $targetCnt != 0 ]]; then...
The solution was to force (i.e., 'convert') the result to an integer, similar to what @John1024 answered above so that it works as expected (Note integer comparison as opposed to string comparison):
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt -ne 0 ]]; then...
==
etc in [[
(also [
aka test
) do string comparison. There are different operators for arithmetic comparison e.g. [[ $targetcnt -ne 0 ]]
; see manpage (or info) under Conditional Expressions. To trim spaces specifically, you could use [
with unquoted variable expansion [ $targetcnt == 0 ]
to get default wordsplitting (NOT done in [[
) but in general that approach leads you into danger.
Commented
Aug 5, 2016 at 7:34
targetCnt=' 0'; [[ targetCnt -ne 0 ]]
would have worked
Commented
Jan 9, 2023 at 17:07
According to Bash documentation, the syntax for the evaluation of an arithmetic expression is $((expression))
. For instance:
$ n=1
$ echo $((n+1))
2
You can use this in a script by assigning an argument to a variable, and then using arithmetic expansion:
n=$1
echo $((n+1))
Test it out:
$ bash ./test.sh 1
2
$ bash ./test.sh 7
8
Do not use $((n))
or similar (e.g., $((n + 0))
et al) if your number may have leading zero(es). Otherwise, your number will be treated as octal. See the following example:
n="057"
n=$((n + 0)
echo $n
Result:
47
10#
, for example $((10#$n))
Other way to manipulate $vars as integers (for real conversion, use eval + string version of the command) is to use let:
i=0
let "i = $i + 1" # i now is 1
echo $i
let "i = $i + 1" # i now is 2
echo $i
Many answers that manipulate as integers, but none of them ACTUALLY converted the var string to INT, as the post asks. They don't solve the problem because they do NOT transform '5' to real 5 for situations like:
for i in {1..$myvar} # number in myvar is seen as string here!
But there is a way, it is to EVAL a string version of the command.
eval "for i in {1..$myvar}; do something; done"