Reputation: 22113
There are two kinds of parameter expansions that return variable names specified on bash documentation.
${!prefix*}
This expansion returns the names of existing variables with names beginning with prefix.${!name[@]}
If name is an array variable, expands to the list of array indices (keys) assigned in name.
There are cases out of the scope:
$ foo=1
$ echo $((${!foo}))
0
$ echo $(!ls)
echo $(ls -l)
total 272 -rw-r--r-- 1 me staff 0 Apr 8 16:37 2
...
What's the mechanism behind it?
Upvotes: 1
Views: 183
Reputation: 531798
${!foo}
and ${!foo*}
are two very different expressions. ${!foo}
expands to the value of the variable whose name is stored in foo
:
$ foo=bar
$ bar=5
$ echo ${!foo} # => echo $bar
5
${!foo*}
expands to the names of variables beginning with foo
$ foo1=1 foo2=2
$ echo ${!foo*}
foo1 foo2
$(!ls)
is not a parameter expansion at all; it is a history subsitution inside a command substitution. !ls
first expands to the most recent command starting with ls
, which is ls -l
in your example. That string is then executed by the command substitution, and the output is captured to be used as the argument to the echo
command.
$ echo $(!ls) => echo $(ls -l) => echo total 272 -rw-r--r-- 1 me staff 0 Apr 8 16:37 2
total 272 -rw-r--r-- 1 me staff 0 Apr 8 16:37 2
Upvotes: 4