1

I came across ${!i} in the body of a for-loop of the form

for ((i=$#; i>0; i--)); do
    # ...
    if <SOME_TEST>; then
        # ...
        accumulator="${!i}:${accumulator}"
        # ...
    fi
    # ...
done

Given this range of possible values, my guess is that ${!i} means something like "expand as the i-th positional argument".

Be that as it may, I'd like to know more about this notation. (In particular, is ${!i} a special case for $@, or is it a particular instance of a syntax applicable to any array? This is why I'm curious about how the expression gets parsed.)

I can't find documentation for this notation, though. If I search the bash man page for the sequence ${!, I find only the following strings

   ${!name[@]}
   ${!name[*]}
   ${!prefix*}
   ${!prefix@}

...and I can't fit the documentation surrounding these occurrences to the code I'm puzzling over.

(Actually, if possible, please quote any relevant documentation in your answer, so that I can sort out why I missed it.)


EDIT: For my original post I copied the wrong for-line from the original code. I've fixed it now. (The interpretation is the same, though.)

0

1 Answer 1

5

You are correct in your assumptions.

The more verbose documentation is hidden away in info bash:

3.5.3 Shell Parameter Expansion

[...]

The basic form of parameter expansion is ${PARAMETER}. The value of PARAMETER is substituted. The PARAMETER is a shell parameter as described above (*note Shell Parameters::) or an array reference (*note Arrays::). The braces are required when PARAMETER is a positional parameter with more than one digit, or when PARAMETER is followed by a character that is not to be interpreted as part of its name.

If the first character of PARAMETER is an exclamation point (!), and PARAMETER is not a NAMEREF, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of PARAMETER as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of PARAMETER itself. This is known as 'indirect expansion'. If PARAMETER is a nameref, this expands to the name of the variable referenced by PARAMETER instead of performing the complete indirect expansion. The exceptions to this are the expansions of ${!PREFIX*} and ${!NAME[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection.

For convenience, you can find this section of the documentation on the GNU.org documentation site too.

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