I have a question about bash's parameter expansion, inside a comma expression, inside an arithmetic expression. I have two statements that I thought should be equivalent, but they're not.
Why does the bash line
n=3; k=10; echo $((n++,k=$n))
output 3
instead of 4
? (It sets n
to 4
, as I expected, but sets k
to 3
.)
In contrast, the bash line
n=3; k=10; echo $((n++,k=n))
outputs 4
, as I expected. (It sets n
to 4
, and k
to 4
also.)
I've tried replacing n++
with ++n
, with n=n+1
, and with n=$((n+1))
in both bash lines, and they all yield the same discrepancy: k=$n
yields 3
in all the scripts, and k=n
yields 4
in all of them.
My understanding is that, if the value of n
is an integer (which it is), $n
and n
should have the same value inside an arithmetic expression. (And this is an arithmetic expression because of the (( ... ))
construct.) According to the bash manual, in the section Arithmetic Evaluation, in an arithmetic expression:
Shell variables are allowed as operands; parameter expansion is performed before the
expression is evaluated. Within an expression, shell variables may also be referenced by
name without using the parameter expansion syntax.
So why is bash treating $n
differently from n
in this example, and exactly how is it evaluating $n
?
I haven't been able to duplicate the issue without using the comma operator. The comma operator, from what I've always seen, computes each of its component subexpressions from left to right, including all the side effects of each component when that component is computed. The value of the comma expression is then the value of the last component computed (the rightmost one).
This question arose in the context of a much more complicated script, and I finally narrowed it down to this simple example which demonstrates the issue.
So, what am I misunderstanding about arithmetic expansion, parameter expansion, or the comma operator?
Note that I'm not looking for a workaround, since I have one already: the version with n
instead of $n
works as I expected. I just want to understand what bash is doing in the version with $n
, and why it does something different from the version with just n
.
$((n++,k=$n))
is first expanded to$((n++,k=3))
(i.e. you "force" parameter expansion) and then evaluated arithmetically, leavingn
to be 4, butk
still at 3. When no parameter expansion is necessary (no$
inside the expression), only the$((n++,k=n))
arithmetic evaluation is performed as per left-to-right order.i=3; echo $(( $i++ ))
(since3++
doesn't make sense)