21
n=0;
((n++));echo "ret=$?;n=$n;"
((n++));echo "ret=$?;n=$n;"
((n++));echo "ret=$?;n=$n;"

from n=1 on, ((n++)) works correctly,
only when n=0, ((n++)) return error,
and I am using a trap '' ERR that is causing trouble with that

is it some bug?

  • I don't think this is a duplicate. Even if you've read the question it's is supposed to be a duplicate of, you still need the information that ((expr)) is equivalent to let "expr" to make the connection. This information is given in the answers to this question. – smheidrich Jul 26 '14 at 23:15

3 Answers3

19

It's because the return value of (( expression )) is not used for error indication. 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".

So, in your case, because the value of the expression is zero, the return status of (( ... )) is 1.

14

The reason is as pmos writes above.

One solution would be to use ((++n)) to do increment. Your expression will never evaluate to zero, and so never look like it causes an error.

  • 2
    to avoid the trap, I did this ((n++))&&:, but your answer works best, unless n=-1, as "most times" n=0 it will work fine :) – Aquarius Power Jul 27 '14 at 18:36
4

You should do:

echo "$((n+=1))"

It will not raise any traps - its only return comes from echo.

Or if you desire to use it as a standalone, in cases in which $n remains less than some 20 digits the following two forms always return true:

n=$((n+1))

Or :

: "$((n+=1))"
mikeserv
  • 58,310
  • this also works every time ((n++))&&: – Aquarius Power Jul 27 '14 at 18:39
  • @AquariusPower - eww. Why in the world would you call out to a nonportable function to increment a variable when you can portably increment same by just evaluating it in the first place? – mikeserv Jul 27 '14 at 19:19
  • my project is in bash :) – Aquarius Power Jul 27 '14 at 20:10
  • @AquariusPower - in my opinion, that doesnt give license for bad habits. It is far better to strive for portability where possible, and to adopt the saner convenience functions where necessary. ((n++))&&: is not among the sane ones. – mikeserv Jul 28 '14 at 00:55
  • you mean that while using bash it may fail for someone else despite it is working here? because my scripts all enforce #!/bin/bash – Aquarius Power Jul 28 '14 at 01:00
  • 1
    @AquariusPower - I mean that someone might someday want to adapt your work, and you shouldnt make it more difficult for no reason. Moreover, you would benefit overall from a more portability aware mindset - understanding how and why things interact on different platforms is a long step in the right direction toward understanding how and why they work at all. And last - have you tried benchmarking your project in a more streamlined shell such as dash vs. bash? My own tests usually point to 2:1 performance benefits when the script is well written. – mikeserv Jul 28 '14 at 01:11
  • 1
    mmm.. I have a script that the more performance it have, the best; I saw ((n++)) wont work in dash, I am thinking on recoding it and I think I will try it with dash, thx on the tip :); also I could find no free and good bash to c compillers.. – Aquarius Power Jul 28 '14 at 01:31
  • @AquariusPower - I'm glad I could convince you. I should note that those performance benefits to which I refer can only ever be realized with regards to memory processing and function declaration/invocation. dash isn't likely to write out a file any quicker than will bash, but it will very likely loop over reading a file with better efficiency. And heredocuments are anonymous pipes in dash - they are not literal tmp files like bash. – mikeserv Jul 28 '14 at 01:38
  • I need to perform string parsing, translating tokens to escaped chars, very fast; hope it works – Aquarius Power Jul 28 '14 at 01:46
  • @AquariusPower - Oh, wow. translating tokens to escaped chars - you mean like this? If you scroll further down to the conversation i had w/ derobert about it, youll see that the second to last line should now read shift ; done ; echo. Anyway, that single quotes an entire argument array - while '\'' quoting any single quotes its arguments contain - in a single iteration per argument while relying only on shell builtins and POSIX code. Or maybe you mean printf \\b\\b\\b\\n | od -An -v -tc -w1? – mikeserv Jul 28 '14 at 01:54
  • @AquariusPower - actually, I can't swear to the portability of those od args, but this is portable: printf \\b\\b\\b\\n |sed -n l – mikeserv Jul 28 '14 at 02:02