这个很难解释。考虑变量all
,first
,last
和some
:
a="apple mcintosh"
b="banana plantain"
c="coconut cashew"
all="$a $b $c"
first="$a"
last=$c"
some="$a $c"
这就是我所拥有的:
echo "What do you want to install?"
echo "all, first, last, or some?"
read userinput
假设用户键入all
,他的输入应被视为变量的名称:我希望下一个命令为pacman -S $all
(相当于pacman -S apple mcintosh banana plantain coconut cashew
)。同样,如果用户同时键入first
和last
,则下一个命令必须为pacman -S $first $last
(实际上应该执行pacman -S apple mcintosh coconut cashew
)。
我使用case/esac
将userinput
转换为变量,但我正在寻找更灵活,更优雅的解决方案,因为此方法不允许多个输入。
case $userinput in
all) result="$all";;
first) result="$first";;
*) exit;;
esac
pacman -S $result
答案 0 :(得分:4)
您所追求的是indirect variable reference,其格式为${!var}
:
3.5.3 Shell参数扩展
[...] 如果参数的第一个字符是感叹号(!),则会引入一个变量间接级别。 Bash使用从参数的其余部分形成的变量的值作为变量的名称;然后展开此变量,并在替换的其余部分中使用该值,而不是参数本身的值。这被称为间接扩张。
例如:
$ 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
要展开多个项目,请使用read -a
将字词读入数组:
$ read -a userinput
first last
$ result=$(for x in ${userinput[@]}; do echo ${!x}; done)
$ echo $result
apple mcintosh coconut cashew
答案 1 :(得分:1)
为了从选择列表中读取用户输入,bash的select
就是您所需要的。此外,当您开始询问“如何动态构建变量名称”时,请考虑关联数组:
a="apple mcintosh"
b="banana plantain"
c="coconut cashew"
declare -A choices
choices[all]="$a $b $c"
choices[first]="$a"
choices[last]="$c"
choices[some]="$a $c"
PS3="What do you want to install? "
select choice in "${!choices[@]}"; do
if [[ -n $choice ]]; then
break
fi
done
echo "you chose: ${choices[$choice]}"
以上不能处理多种选择。在那种情况下,然后(仍然使用上面的“选择”数组):
options=$(IFS=,; echo "${!choices[*]}")
read -rp "What do you want to install ($options)? " -a response
values=""
for word in "${response[@]}"; do
if [[ -n ${choices[$word]} ]]; then
values+="${choices[$word]} "
fi
done
echo "you chose: $values"
这使用read
的{{1}}选项将响应读入数组。它看起来像:
-a