Score:5

Increment operator does not work on a variable if variable is set to 0

br flag

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.

pLumo avatar
in flag
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](https://developpaper.com/functions-of-in-linux-shell-2))
wjandrea avatar
cn flag
Sidenote: there's more than one way to [increment a variable in Bash](/q/385528/301745). Probably the most idiomatic is to explicitly make it an integer first: `declare -i a=0` then `a+=1`.
ilkkachu avatar
co flag
@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)
Saad Abdul Majid avatar
br flag
@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.
Score:10
cn flag

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.

wizzwizz4 avatar
de flag
Technically, the increment occurs before the return; however, the returned value is the value taken before the increment.
Score:5
jp flag

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
pLumo avatar
in flag
check `echo $?`.
sudodus avatar
jp flag
@pLumo, echo $((a++)) prints before update, echo $((++a)) prints after update.
bac0n avatar
cn flag
Arithmetic expansion does not emit an exit status does not see the connection?
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.