How to increment a variable in bash?
Solution 1
There is more than one way to increment a variable in bash
, but what you tried will not work.
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: https://tldp.org/LDP/abs/html/dblparens.html.
Solution 2
var=$((var + 1))
Arithmetic in bash uses $((...))
syntax.
Solution 3
Various options to increment by 1, and performance analysis
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:
- Is there a performance difference between them?
- 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 built into bash.
Solution 4
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.
Solution 5
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
Related videos on Youtube
Patrick Hellebrand
Updated on September 18, 2022Comments
-
Patrick Hellebrand 3 months
I have this script in jQuery, it scrolls to wanted section but with spacing to the top. It works fine on all tested browsers ... except firefox.
$('nav > *').click(function(event){ event.preventDefault(); var navClicked = $(this).index(); var elem = $(this).attr("href"); $('body').scrollTop($(elem).offset().top - 48); });
-
frnt over 6 yearsadd your html codes too or create a jsfiddle.
-
Patrick Hellebrand over 6 years@frnt jsfiddle.net/5L3xyuuv/1
-
vsync over 6 yearswhat kind of a test page is that? it's almost empty and doesn't reproduce the problem
-
vsync over 6 yearswhy did you do all this javascript anyway if it simply "jumps" to the
id
location on the page like a regular hash link does? -
Patrick Hellebrand over 6 yearsbecause your 'jump' ignores the header height if theres one
-
-
gniourf_gniourf about 9 yearsor
((++var))
or((var=var+1))
or((var+=1))
. -
Javier López about 9 yearsor var=$(expr $var + 1)
-
phunehehe over 8 yearsCuriously,
var=0; ((var++))
returns an error code whilevar=0; ((var++)); ((var++))
does not. Any idea why? -
phunehehe over 8 years@RaduRădeanu I'm sure, the same thing happens in zsh too. Actually maybe I didn't make myself clear. This prints 1 (an error code) instead of 0 (successful):
var=0; ((var++)); echo $?
. -
Radu Rădeanu over 8 years@phunehehe Look at
help '(('
. The last line says:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
-
DreadPirateShawn over 8 yearsI suspect the evaluation of zero as
1
is why @gniourf_gniourf's tip includes((++var))
but not((var++))
. -
rubo77 about 7 yearsSo which is the most compatible way?
-
ArtOfWarfare over 6 yearsVastly 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. -
Patrick Hellebrand over 6 yearsyour snippet works fine, but if ill copy it to my snippet, it stops working
-
Patrick Hellebrand over 6 yearsCould it be, that other jquery scripts cause this, but only on firefox?
-
frnt over 6 yearsThen you need to go through your codes, as per your query this works perfectly fine on all browser.
-
MatthewRock almost 6 yearsApparently speed correlates with command length. I wonder whether the commands call the same functions.
-
wjandrea over 5 yearsis it safe to use
let var++
, without the quotes? -
wjandrea over 5 yearsYou can also use
i=$((i+1))
-
Radon Rosborough over 5 yearsIf process substitution
$(...)
is available on this shell, I'd recommend using it instead. -
Daniel Eisenreich about 5 years
((val++))
doesn't worked in my case. But if I use((++val))
this worked. Some suggestions why? -
arielf over 4 years@DanielEisenreich both forms seem to work fine in
bash
version 4.3.48. Maybe you have an old version?$ val=0; echo $val; ((val++)); echo $val
gives me: 0 1 ` -
Laurence Renshaw over 4 yearslet only needs quotes if you put spaces in your expression
-
x-yuri about 4 years@arielf You don't observe the behavior since most likely you don't
set -e
. -
Sandeep about 4 yearsI'm surprised that
$((var+1))
works. I would have expected$(($var+1))
. -
x-yuri almost 4 yearsTo make
(( var++ ))
work (not fail whenvar == 0
) withset -e
, do: $(( var++ ))
. -
raygozag about 3 yearsNot what the OP asked.
-
Keith Reynolds about 3 years@raygozag The op asked how to increment. My answer first list many methods. How does that not directly answer the op question? Then it provide time information for each method. All that is, is just extra information to assist the op in choosing which method he wants to use.
-
raygozag about 3 yearsIt was already answered, the OP did not ask for performance evaluations, no matter how helpful you want to be, they didn't ask for it.
-
Jon Spencer almost 3 yearsI found that on Bash 3.2.57, using
declare -i x
and then doingx+=1
in a loop (doing other thing),x
did not increment more than one time. Thelet
and(())
methods worked fine. -
sastorsl over 2 years@JonSpencer you might be hitting this? unix.stackexchange.com/questions/402750/…
-
Timo about 2 yearsUse a mix of let and arithmetic expanison and you are good to go.
-
Sephethus about 2 yearsWhy do absolutely none of these options anywhere work for me? I'm getting things like i++: not found or ++i not found or let not found or any number of errors. WTF?
-
Satoshi Nakamoto 10 monthsJust to rememeber:
++var
is prefix andvar++
is postfix, there is a difference.