I have tried to increment a numeric variable using both var=$var+1 and var=($var+1) without success. The variable is a number, though bash appears to be reading it as a string.

Bash version 4.2.45(1)-release (x86_64-pc-linux-gnu) on Ubuntu 13.10.

up vote 737 down vote accepted

There is more than one way to increment a variable in bash, but what you tried is not correct.

You can use for example arithmetic expansion:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))

Or you can use let:

let "var=var+1"
let "var+=1"
let "var++"

See also: http://tldp.org/LDP/abs/html/dblparens.html.

  • 23
    or ((++var)) or ((var=var+1)) or ((var+=1)). – gniourf_gniourf Dec 3 '13 at 18:30
  • or var=$(expr $var + 1) – Javier López Dec 3 '13 at 23:20
  • 2
    Curiously, var=0; ((var++)) returns an error code while var=0; ((var++)); ((var++)) does not. Any idea why? – phunehehe Mar 26 '14 at 9:36
  • 12
    @phunehehe Look at help '(('. The last line says: Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise. – Radu Rădeanu Mar 27 '14 at 11:41
  • 4
    is it safe to use let var++, without the quotes? – wjandrea Jun 14 '17 at 20:20
var=$((var + 1))

Arithmetic in bash uses $((...)) syntax.

  • 4
    Vastly better than the accepted answer. In just 10% as much space, you managed to provide enough examples (one is plenty - nine is overkill to the point when you're just showing off), and you provided us with enough info to know that ((...)) is the key to using arithmetic in bash. I didn't realize that just looking at the accepted answer - I thought there was a weird set of rules about order of operations or something leading to all of the parenthesis in the accepted answer. – ArtOfWarfare Jun 22 '16 at 13:56

Performance Analysis of various options

Thanks to Radu Rădeanu's answer that provides the following ways to increment a variable in bash:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))
let "var=var+1"
let "var+=1" 
let "var++"

There are other ways too. For example, look in the other answers on this question.

let var++
var=$((var++))
((++var))
{
    declare -i var
    var=var+1
    var+=1
}
{
    i=0
    i=$(expr $i + 1)
}

Having so many options leads to these two questions:

  1. Is there a performance difference between them?
  2. If so which, which performs best?

Incremental performance test code:

#!/bin/bash

# To focus exclusively on the performance of each type of increment
# statement, we should exclude bash performing while loops from the
# performance measure. So, let's time individual scripts that
# increment $i in their own unique way.

# Declare i as an integer for tests 12 and 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Set i for test 14.
echo > t14 'i=0; i=$(expr $i + 1)'

x=100000
while ((x--)); do
    echo >> t0 'i=$((i+1))'
    echo >> t1 'i=$((i++))'
    echo >> t2 '((i=i+1))'
    echo >> t3 '((i+=1))'
    echo >> t4 '((i++))'
    echo >> t5 '((++i))'
    echo >> t6 'let "i=i+1"'
    echo >> t7 'let "i+=1"'
    echo >> t8 'let "i++"'
    echo >> t9 'let i=i+1'
    echo >> t10 'let i+=1'
    echo >> t11 'let i++'
    echo >> t12 'i=i+1'
    echo >> t13 'i+=1'
    echo >> t14 'i=$(expr $i + 1)'
done

for script in t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; do
    line1="$(head -1 "$script")"
    printf "%-24s" "$line1"
    { time bash "$script"; } |& grep user
    # Since stderr is being piped to grep above, this will confirm
    # there are no errors from running the command:
    eval "$line1"
    rm "$script"
done

Results:

i=$((i+1))              user    0m0.992s
i=$((i++))              user    0m0.964s
((i=i+1))               user    0m0.760s
((i+=1))                user    0m0.700s
((i++))                 user    0m0.644s
((++i))                 user    0m0.556s
let "i=i+1"             user    0m1.116s
let "i+=1"              user    0m1.100s
let "i++"               user    0m1.008s
let i=i+1               user    0m0.952s
let i+=1                user    0m1.040s
let i++                 user    0m0.820s
declare -i i; i=i+1     user    0m0.528s
declare -i i; i+=1      user    0m0.492s
i=0; i=$(expr $i + 1)   user    0m5.464s

Conclusion:

It seems bash is fastest at performing i+=1 when $i is declared as an integer. let statements seem particularly slow, and expr is by far the slowest because it is not a builtin.

  • Apparently speed correlates with command length. I wonder whether the commands call the same functions. – MatthewRock Jan 5 '17 at 15:40
  • 1
    i=(expr ...) is a syntax error. Did you mean i=$(expr ...)? – muru Jun 15 '17 at 6:18
  • @muru fixed, and added a check into the for loop. – wjandrea Jun 15 '17 at 17:08

There's also this:

var=`expr $var + 1`

Take careful note of the spaces and also ` is not '

While Radu's answers, and the comments, are exhaustive and very helpful, they are bash-specific. I know you did specifically ask about bash, but I thought I'd pipe in since I found this question when I was looking to do the same thing using sh in busybox under uCLinux. This portable beyond bash.

  • You can also use i=$((i+1)) – wjandrea Jun 14 '17 at 22:58
  • If process substitution $(...) is available on this shell, I'd recommend using it instead. – Radon Rosborough Aug 24 '17 at 18:54

If you declare $var as an integer, then what you tried the first time will actually work:

$ declare -i var=5
$ echo $var
5
$ var=$var+1
$ echo $var
6

Reference: Types of variables, Bash Guide for Beginners

There's one method missing in all the answers - bc

$ VAR=7    
$ bc <<< "$VAR+2"
9
$ echo $VAR
7
$ VAR=$( bc <<< "$VAR+1" )
$ echo $VAR
8

bc is specified by POSIX standard, so should be present on all versions of Ubuntu and POSIX-compliant systems. The <<< redirection could be altered to echo "$VAR" | bc for portability, but since the question asks about bash - it's OK to just use <<<.

The return code 1 issue is present for all default variants (let, (()), etc.). This often causes trouble, e.g., in scripts that use set -o errexit. Here is what I am using to prevent error code 1 from math expressions that evaluate to 0;

math() { (( "$@" )) || true; }

math a = 10, b = 10
math a++, b+=2
math c = a + b
math mod = c % 20
echo $a $b $c $mod
#11 12 23 3

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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