bashindirection

What is indirect expansion? What does ${!var*} mean?


I'm reading "Bash Guide for Beginners". It says:

If the first character of PARAMETER is an exclamation point, 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.

The example given is:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

I don't quite understand here:

the value of the variable formed from the rest of PARAMETER

As the PARAMETER is just !N*, then

the rest of PARAMETER

is just N*. How could this form a variable? Did Bash search all possible commands there?


Solution

  • If you read the bash man page, it basically confirms what you have stated:

    If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. 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.

    However, reading on from there:

    The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below.

    ${!prefix*} Names matching prefix. Expands to the names of variables whose names begin with prefix, separated by the first character of the IFS special variable.

    In other words, your particular example ${!N*} is an exception to the rule you quoted. It does, however, work as advertised in the expected cases, such as:

    $ export xyzzy=plugh ; export plugh=cave
    
    $ echo ${xyzzy}  # normal, xyzzy to plugh
    plugh
    
    $ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
    cave
    

    An example of ${!prefix*}:

    $ xyzzy=plugh
    $ xyzzz=flume
    
    $ echo ${!xyzz*}
    xyzzy xyzzz