6

Incrementing a variable var works in bash when enclosed in double parentheses like (( var++ )). But I have found that it fails if variable is set to 0 beforehand like var=0.

$ a=0
$ ((a++)) && echo "command succeeded" || echo "command failed"
command failed

$ a=1
$ ((a++)) && echo "command succeeded" || echo "command failed"
command succeeded

Can someone explain this behavior?

Environment:

I am using gnome-terminal on Ubuntu Desktop 18.04.5 LTS.

4
  • 4
    I think you should not really on the exit status of (( to know if the command was working.. >> "If the result of the expression is 0, the exit status code returned will be 1 or “false”, while the exit status code returned by a non-zero value expression will be 0 or “true”." (via)
    – pLumo
    Dec 8, 2021 at 15:56
  • 1
    Sidenote: there's more than one way to increment a variable in Bash. Probably the most idiomatic is to explicitly make it an integer first: declare -i a=0 then a+=1.
    – wjandrea
    Dec 9, 2021 at 0:16
  • @pLumo, it's not the exit status that's wrong, but the users' assumptions (yours, too). It works exactly like post-increment is defined, and exactly like it does in e.g. C. Though you're right in that you can't use the exit status of (( .. )) to see if it worked, since a syntax error also makes it exit with status 1. (and not e.g. 2, like [ and [[ do)
    – ilkkachu
    Dec 9, 2021 at 10:05
  • @pLumo, exit status code is of concern to me because script is using trap ... ERR and this line provokes it. I have avoided this scenario, for now, by using pre-increment as my base value is 0 for var. But this solution is specific to my use case. Maybe I should search for a way to bypass trap for such/selected statements.
    – Saad
    Dec 11, 2021 at 7:48

2 Answers 2

10

With credit from here: https://unix.stackexchange.com/questions/146773/why-bash-increment-n-0n-return-error

The return value of (( expression )) does not indicate an error status, but, from the bash manpage:

((expression)) The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".

In ((a++))you are doing a post increment. The value of a is 0 so 1 is returned, after that, it is incremented.

Compare

$ unset a
$ ((a++)) ; echo Exitcode: $? a: $a
Exitcode: 1 a: 1

versus

$ unset a
$ ((++a)) ; echo Exitcode: $? a: $a
Exitcode: 0 a: 1

A pre-increment, so a has become 1 and 0 is returned.

1
  • Technically, the increment occurs before the return; however, the returned value is the value taken before the increment.
    – wizzwizz4
    Dec 9, 2021 at 18:06
6

This works for me (in bash in Ubuntu),

$ a=0
$ echo $((a++))
0
$ echo $((a++))
1
$ echo $((a++))
2
$ echo $((a++))
3
$ echo $a
4

Notice the difference with

$ a=0
$ echo $((++a))
1
$ echo $((++a))
2
$ echo $((++a))
3
$ echo $a
3
3
  • 2
    check echo $?.
    – pLumo
    Dec 8, 2021 at 15:48
  • 2
    @pLumo, echo $((a++)) prints before update, echo $((++a)) prints after update.
    – sudodus
    Dec 8, 2021 at 15:51
  • Arithmetic expansion does not emit an exit status does not see the connection?
    – user986805
    Dec 8, 2021 at 17:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .