所以我试图为我的服务器制作一个小的自定义管理脚本,但是我遇到了一个问题,即创建具有正确结果的菜单脚本。
我有以下脚本
function config
{
list=''
declare -a programs=("docker" "IdontExist" "pushover" "IdontexistEither")
for program in "${programs[@]}"
do
#Check if command exists on the server
if hash $program 2>/dev/null; then
list="${list} \"${program}\""
fi
done
title="Config manager"
prompt="Pick an option:"
options=(${list})
echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"; do
case "$REPLY" in
#Dont know how to create this section in a script
1 ) echo "Update Docker"; break;;
3 ) echo "Update IdontExist"; break;;
2 ) echo "Update mytest"; break;;
4 ) echo "Update IdontExistEither"; break;;
$(( ${#options[@]}+1 )) ) echo "Goodbye!"; break;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
}
我的列表变量如下所示
list: "docker" "pushover"
所以我在上面脚本中的选项将无法正常工作。如何创建选项,具体取决于列表变量?
我还想根据所选的选项调用某些函数,例如,如果有人选择“docker”我想调用一个名为:_docker_config的函数,当它的“pushover”我将调用一个名为_pushover_config的函数时我也在剧本中实现了这一点?
答案 0 :(得分:2)
问题在于您正在测试$REPLY
而不是$opt
:
select opt in "${options[@]}" "Quit"
do
if [[ -z $opt ]]; then
echo "Didn't understand \"$REPLY\" "
REPLY=
else
case "$opt" in
docker)
echo "Update Docker"
break;;
IdontExist)
echo "Update IdontExist"
break;;
pushover)
echo "Update mytest"
break;;
IdontexistEither)
echo "Update IdontExistEither"
break;;
Quit)
echo "Goodbye!"
break;;
*)
echo "Invalid option <$opt>. Try another one."
;;
esac
fi
done
如果您使用$opt
,那么您不需要将菜单编号(在您的情况下是可变的)与实际条目(程序名称)匹配 - select
为您执行此操作。您需要$REPLY
的唯一时间是它无效(将REPLY
设置为空字符串会在下一次迭代时重新显示菜单)。
并非case
语句中的所有选项都适用于每次运行,但这没关系,因为$opt
只会被有效的填充,而其他选项将不可见用户。
你不需要continue
,它通过循环为你做到了。
编辑:
这是使用关联数组而不是case语句的替代方法。它使菜单和测试成为动态。在显示的情况下,只有两个选项具有功能,但不一定是这种情况,它可以是任何数字(有原因)。
_docker_config()
{
echo "Welcome to docker"
}
_pushover_config()
{
echo "Welcome to pushover"
}
# This declares and associative array with the keys being the menu items
# and the values being the functions to be executed.
# This will have to include all possible programs
declare -A functab=(["Docker"]=_docker_config
["Pushover"]=_pushover_config)
title="Config manager"
prompt="Pick an option:"
# The options are hard-coded here, of course you will dynamically generate it
# I omitted that for testing purposes
declare -a options=("Docker" "IdontExist" "Pushover" "IdontexistEither")
echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"
do
if [[ $opt == "Quit" ]]; then
echo "Goodbye!"
break
fi
if [[ -z $opt ]]; then
echo "Didn't understand \"$REPLY\" " >&2
REPLY=
else
# Here we check that the option is in the associative array
if [[ -z "${functab[$opt]}" ]]
then
echo "Invalid option. Try another one." >&2
else
# Here we execute the function
eval ${functab[$opt]} # See note below
fi
fi
done
eval 会谨慎使用。通常这是一个要避免的命令,因为它可能是一个安全问题,但是我们正在检查有效的条目,因此在这种情况下它是合理的。只是不要过度使用它。