When I use arithmetic expansion in an array index in bash, like this:
declare -a FILES
declare -i INDEX=0
for FILE in ./*
do
FILES[((INDEX++))]=\"$FILE\
The dollar sign is required in some contexts but not the others:
$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
$ echo ((1+2))
bash: syntax error near unexpected token `('
$ echo $((1+2))
3
$ for ((x=0; x<3;++x)); do echo $x; done
0
1
2
$ for $((x=0; x<3;++x)); do echo $x; done
bash: `$((x=0; x<3;++x))': not a valid identifier
After reading bash man page, the dollar sign is not required in compound commands:
Compound commands are the shell programming constructs. Each construct begins with a reserved word or control operator and is terminated by a corresponding reserved word or operator. Any redirections (see Redirections) associated with a compound command apply to all commands within that compound command unless explicitly overridden.
In most cases a list of commands in a compound command’s description may be separated from the rest of the command by one or more newlines, and may be followed by a newline in place of a semicolon.
Bash provides looping constructs, conditional commands, and mechanisms to group commands and execute them as a unit.
for (( expr1 ; expr2 ; expr3 ))
is a compound command and hence the dollar sign is not required to enable arithmetic evaluation.
Whereas echo $((expr))
is not a compound command because it does not start with a reserved bash keyword, so it requires a dollar sign to enable arithmetic evaluation.
In arrays, bash considers expressions between []
as arithmetic. Thus
i=2 ; f[i++]=10
is perfect. Writing f[((i++))]
is also correct but in this case, (())
is not seen as the arithmetic expansion operator, but as nested parentheses.
Note that ((expr))
evaluates expr
, then succeeds if it is true, while$((expr))
is expanded as its value. So f[$((i++))]
is also correct.
Finally, f[$i++]
is not what you want since $i
is expanded first. For instance, i=j ; f[$i++]
will be expanded as f[j++]
.
Remark: a strange feature is that bash expands all it can in arithmetic mode without the $
sign:
$ unset i j k f
$ i=j ; j=k ; k=5 ; f[i++]=10
$ declare -p i j k f
declare -- i="6"
declare -- j="k"
declare -- k="5"
declare -a f='([5]="10")'