98

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
  • I try to format your question, but it remains somehow unclear. printf "1 + %s\n" $1 won't do ? – Archemar Sep 27 '15 at 19:50
109

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.

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
| improve this answer | |
  • 2
    Using $(( )) or (( )) is unsafe if you don't know what the strings are (like user input). Consider this: foo=foo (( foo += 0 )) This will crash the script as it tries to recursively evaluate foo. Same with: foo=foo foo=$(( foo + 0 )) – art Aug 5 '16 at 2:00
  • This only works if you know that the variable holds a valid integer. I have lots of tests in my answer stackoverflow.com/a/59781257/117471 – Bruno Bronosky Jan 17 at 5:02
  • bc #isthashiznit , thanks for that one – jsaddwater Jan 24 at 13:26
18

Other way, you can use expr

Ex:

$ version="0002"
$ expr $version + 0
2
$ expr $version + 1
3
| improve this answer | |
  • this crashed and died if I had characters after the number. I was trying to test battery percentage. when it got below 10, if always died because of the period. The solution below worked beautifully. – Eric Sebasta Aug 1 at 19:23
12

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
| improve this answer | |
  • 3
    In other shells without printf -v this can be achieved with command substitution: int="$(printf '%d' 123.123 2>/dev/null)" – Adrian Günter Apr 13 '18 at 19:11
10

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:

targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
| improve this answer | |
  • 4
    == 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. – dave_thompson_085 Aug 5 '16 at 7:34
-2

care about color codes, even in trace (-x) they won't appear, what would give it away is that the string that is supposed to be a number is wrapped in quotes no matter how you print it.

| improve this answer | |
  • 1
    Voted down, as I find your answer a bit unclear. Perhaps you could add what the script should be corrected to? – Time4Tea Feb 1 '18 at 21:28
  • this was the top answer in search for bash+integer+string so I added a piece of information related to it which was not included among the answers, that is when strings are wrapped in colors codes it might be unclear why operations such as $((var+var)) fail even though if you echo or printf both vars they are the same. I don't know the fix since I only was able to fix it by disabling color codes at the source of the output. To spot it in the trace logs you will see the offending variable assigned as var='0' while it should simply be var=0 – untore Feb 2 '18 at 5:36
  • What you can do is make sure the output does not have color codes with sed if you can't disable it – untore Feb 2 '18 at 5:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.