This one is kind of hard to explain. Consider variables all
, first
, last
, and some
:
a="apple mcintosh"
b="banana plantain"
c="coconut cashew"
all="$a $b $c"
first="$a"
last=$c"
some="$a $c"
Here is what I have:
echo "What do you want to install?"
echo "all, first, last, or some?"
read userinput
Assuming that the user types all
, his input shall be treated as the name of a variable: I want the next command to be pacman -S $all
(equivalent to pacman -S apple mcintosh banana plantain coconut cashew
). Likewise, if the user types both first
and last
, the next command has to be pacman -S $first $last
(which in fact should execute pacman -S apple mcintosh coconut cashew
).
I used case/esac
to translate userinput
into a variable, but I am looking for a more flexible and elegant solution, as this approach doesn't allow more than one input.
case $userinput in
all) result="$all";;
first) result="$first";;
*) exit;;
esac
pacman -S $result
What you're after is an indirect variable reference, which has the form ${!var}
:
3.5.3 Shell Parameter Expansion
[...] 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.
For example:
$ a="apple mcintosh"
$ b="banana plantain"
$ c="coconut cashew"
$ all="$a $b $c"
$ first="$a"
$ last="$c"
$ some="$a $c"
$ read userinput
all
$ result=${!userinput}
$ echo $result
apple mcintosh banana plantain coconut cashew
To expand multiple items, use read -a
to read words into an array:
$ read -a userinput
first last
$ result=$(for x in ${userinput[@]}; do echo ${!x}; done)
$ echo $result
apple mcintosh coconut cashew