arrays - 重复选择菜单提示的最佳方式
问题描述
从这个问答和另一个关于如何从数组中删除空白的有用答案中,我整理了一个简单的菜单对话框,允许用户在数组中“添加”和“删除”选项。然后可以将此“选定选项”数组作为输入传递给脚本/函数以执行操作。
问题:有没有比重复select
循环更好的方法来重复提示?进入一个循环只是为了打破它以重复循环菜单似乎有点奇怪?
有人建议我使用select
循环进行菜单选择。但我想知道是否有其他东西更适合多选菜单,因为它是动态更新的,所以应该重复提示?
我在想只是用case
和使用echo
或printf
重复菜单对话框交换条件语句会简化脚本。但好奇是否有人知道更好的方法。
#!/bin/bash
emailAliasMenu() {
# About: Interactive two-tier menu to select Email Aliases from user input
# Usage: Pass arrays of menu items into function as argumments 1 (parent array) and 2 (child array).
# Example: startMenuTier parentMenuItems childMenuItems
declare -n outputArray="${1}"
initMenus() {
parentOptMenu=("default" "add" "remove" "exit") # Parent navigation menu
optMenu=("info" "scheduling" "hr" "contact" "feedback") # Child navigation menu
optUnselected=("${optMenu[@]}") # Declare array for unselected options
optSelected=() # Declare array for selected aliases
optSelectedDef=("${optUnselected[0]}" "${optUnselected[1]}")
PS3="$parentOptPrompt"
dynaVars=( parentOptMenu optMenu optUnselected optSelected optSelectedDef )
parentOptPrompt="Enter number for desired action: "
optExitNotif="Moving up a menu..."
errorNotif="Invalid choice. Be sure to enter a number. Try again."
}
removeArrayBlanks() {
# Usage: Provide array as input. Function removes empty items and rebuilds array.
# Example 1: removeArrayBlanks myArray
# Example 2: readarray -t newArray < <(removeArrayBlanks "hate" "" "empty" "array" "items")
if [[ $# -eq 1 ]]; then # Input is an array variable.
declare -n localArray="${1}" # Declare variable 'linked' to input (i.e. same namespace)
elif [[ $# -gt 1 ]]; then # Input is a free array.
declare localArray=( "${@}" ) # Put input array arguments into new array
else echo "Usage: Provide array variable or array as an argument." && exit 1
fi
for i in "${!localArray[@]}"; do
[[ -n "${localArray[${i}]}" ]] && finalArray+=( "${localArray[$i]}" ) # Add non-empty strings
done && printf '%s\n' "${finalArray[@]}"
localArray=( "${finalArray[@]}" ) && unset finalArray && unset -n localArray # Store new array in namespace variable and clean up
}
endOptMenu() {
removeArrayBlanks optSelected
removeArrayBlanks optUnselected
optSummary="Selected options are: ${optSelected[*]}."
printf '\n%s\n' "$optSummary"
}
unsetVars() {
for i in "${!dynaVars[@]}"; do
unset "${dynaVars[${i}]}"
done
unset -n "outputArray"
}
initMenus
while true ; do # Display menu continuously until exit
PS3="$parentOptPrompt"
select opt in "${parentOptMenu[@]}" ; do # Parent menu for top level actions
optPrompt="Enter number to '$opt' email alias or 'exit': " # Define prompt for child menus
[[ $opt == "default" ]] && optSelected=("${optSelectedDef[@]}") && for i in "${optSelectedDef[@]}"
# Uses default aliases and exits menu.
do
optUnselected=("${optUnselected[@]/$i/}")
done && echo "$optExitNotif" && endOptMenu && break
[[ $opt == "add" ]] && PS3="$optPrompt" && while true ; do
select subOpt in "${optUnselected[@]}" "exit" ; do
# Lists unselected options. Upon entry, remove and add to selected options.
if [[ "$subOpt" == "exit" ]]; then
echo "$optExitNotif" && break 3
elif [[ "$subOpt" ]]; then
optSelected+=("$subOpt") && optUnselected=("${optUnselected[@]/$subOpt/}") && endOptMenu && break 1
else
echo "$errorNotif" && break 1
fi
done
done
[[ $opt == "remove" ]] && PS3="$optPrompt" && while true ; do
select subOpt in "${optSelected[@]}" "exit" ; do
# Lists selected options. Upon entry, remove and add to unselected options.
if [[ "$subOpt" == "exit" ]]; then
echo "$optExitNotif" && break 3
elif [[ "$subOpt" ]]; then
optUnselected+=("$subOpt") && optSelected=("${optSelected[@]/$subOpt/}") && endOptMenu && break 1
else
echo "$errorNotif" && break 1
fi
done
done
[[ $opt == "exit" ]] && break 2
[[ ! $opt ]] && echo "$errorNotif" && break 1
done
done
outputArray=( "${optSelected[@]}" ) && printf '%s\n' "Final selection: ${outputArray[*]}" "Sent to array '${1}'" && unsetVars
}
解决方案
推荐阅读
- ios - 如何通过隐藏导航栏来使用 XLPagerTabStrip 库?
- javascript - 页脚不在应有的下方。我需要它低于所有其他元素
- vba - Basic Visual Basic 程序错误 - 可能是变量/语法错误(标记为 Fat)
- c# - 单击时的 C# 文本框显示下拉列表,其中输入了先前的值
- c++ - 嵌套类模板类型别名
- httprequest - 使用 Power Automate HTTP 请求将列表字段聚合设置为 SUM
- python - Python BeautifulSoup IndexError:列表索引超出范围
- apache - rsync ssh stdout 和/或 stderr 到浏览器/网站
- python - 使用 Selenium/Python 在 div 中提取一个字符串,该字符串包含许多其他 div 和自己的字符串
- html - 带有图片和声音的 html/ts 按钮 - 声音不起作用,所以出了什么问题?