如何在whiptail菜单中使用数组?时区选择脚本报错排查
问题描述
在搭载systemd的Linux机器上编写脚本,想用数组在whiptail中显示时区列表,脚本如下:
tzones=$(timedatectl list-timezones) arr=( $tzones ) count=0 for i in "${arr[@]}"; do allzones[$count]=$(echo "\"$i\""); ((count=count+1)); done for i in "${allzones[@]}"; do echo $i; done #So I know I have a list of items in quotes at this point whiptail --title "Time zone" --menu "Select time zone" 25 78 16 "${allzones[@]}"
执行后Bash一直输出whiptail的帮助菜单,无法正常显示时区选择菜单。
问题原因
whiptail的--menu选项要求每个列表项必须是成对的参数:显示文本和对应的返回值。你当前构造的数组是每个元素带引号的单个字符串,不符合参数格式,导致whiptail识别失败,输出帮助菜单。
解决方案
方法1:修正数组构造逻辑
无需给时区字符串手动加引号,而是为每个时区添加对应的返回值(直接用时区本身即可),构造成对的数组元素:
# 初始化空数组 allzones=() # 遍历所有时区,每一项添加两次(显示文本 + 返回值) while IFS= read -r tz; do allzones+=("$tz" "$tz") done < <(timedatectl list-timezones) # 调用whiptail菜单 whiptail --title "Time zone" --menu "Select time zone" 25 78 16 "${allzones[@]}"
方法2:更简洁的写法
用mapfile读取时区到数组,再构造菜单参数:
# 读取所有时区到数组tzones mapfile -t tzones < <(timedatectl list-timezones) # 构造菜单参数数组 allzones=() for tz in "${tzones[@]}"; do allzones+=("$tz" "$tz") done whiptail --title "Time zone" --menu "Select time zone" 25 78 16 "${allzones[@]}"
补充说明
- 手动给时区加引号是多余操作,Bash会自动处理带空格的参数,反而会导致whiptail无法识别正确的成对参数。
- 使用
while IFS= read -r或mapfile是更健壮的写法,能兼容所有合法时区名称(即使包含特殊字符)。
内容的提问来源于stack exchange,提问作者megalamehaxxor
相关产品推荐
相关产品推荐

