我想发出一个类似下面这样的bash命令:
whiptail --title 'Select Database' --radiolist 'Select Database:' 10 80 2 \
1 production off \
2 localhost on对于如何指定单选项列表值,Whiptail是相当特别的。它们必须分别在各自的线路上提供,如下所示。Here is a good article on this question。
数据库列表在一个名为DBS的变量中可用,ACTIVE_DB是要在whiptail对话框中突出显示的radiolist项。
这是我目前为构建命令行所做的努力。这可能太复杂了。
DBS="production localhost"
ACTIVE_DB="localhost"
DB_COUNT="$( echo "$DBS" | wc -w )"
DB_LIST="$(
I=1
echo ""
for DB in $DBS; do
SELECTED="$( if [ "$DB" == "$ACTIVE_DB" ]; then echo " on"; else echo " off"; fi )"
SLASH="$( if (( $I < $DB_COUNT )); then echo \\; fi )"
echo " $I $DB $SELECTED $SLASH"
echo ""
I=$(( I + 1 ))
done
)"
OPERATION="whiptail \
--title \"Select Database\" \
--radiolist \
\"Select Database:\" \
10 80 $DB_COUNT \"${DB_LIST[@]}\""
eval "${OPERATION}"我离得很近。正如您所看到的,扩展包含将事情搞乱的单引号,并且在一些EOL中缺少反斜杠:
set -xv
++ whiptail --title 'Select Database' --radiolist 'Select Database:' 10 80 2 '
1 production off
2 localhost on '解决方案需要提供一种方法,以某种方式知道用户做出了哪些选择,或者是否按了ESC。ESC通常将返回代码设置为255,因此这不是很困难,但是当尝试检索用户选择的radiolist项的值时,这个问题会变得非常混乱。
发布于 2019-05-01 08:17:12
以下内容遵循BashFAQ #50中列出的最佳实践
# note that lower-case variable names are reserved for application use by POSIX
# see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
active_db="localhost"
dbs=( production localhost ) # using an array, not a string, means ${#dbs[@]} counts
# initialize an array with our explicit arguments
whiptail_args=(
--title "Select Database"
--radiolist "Select Database:"
10 80 "${#dbs[@]}" # note the use of ${#arrayname[@]} to get count of entries
)
i=0
for db in "${dbs[@]}"; do
whiptail_args+=( "$((++i))" "$db" )
if [[ $db = "$active_db" ]]; then # only RHS needs quoting in [[ ]]
whiptail_args+=( "on" )
else
whiptail_args+=( "off" )
fi
done
# collect both stdout and exit status
# to grok the file descriptor switch, see https://stackoverflow.com/a/1970254/14122
whiptail_out=$(whiptail "${whiptail_args[@]}" 3>&1 1>&2 2>&3); whiptail_retval=$?
# display what we collected
declare -p whiptail_out whiptail_retval虽然我没有现成的whiptail来测试,但上面代码运行的确切调用完全相同于:
whiptail --title "Select Database" \
--radiolist "Select Database:" 10 80 2 \
1 production off \
2 localhost on ...as一个字符串,当执行evaled时,它运行精确的命令,可以用以下命令生成:
printf '%q ' whiptail "${whiptail_args[@]}"; echo发布于 2019-05-01 08:19:30
使用数组。他们会让这件事变得简单十倍。让我们从小事做起,一路向上。下面是数组形式的$DBS和$DB_COUNT:
DBS=(production localhost)
DB_COUNT=${#DBS[@]}这里的优点是$DBS实际上有两个条目,所以我们可以使用${#DBS[@]}来计算条目的数量,而不必向外部命令(如wc )提供外壳。
所以现在让我们来处理$DB_LIST。您正尝试在每次循环迭代中添加几个选项。让我们将其转换为数组语法,使用array+=(foo bar baz)来追加项。
DB_LIST=()
I=1
for DB in "${DBS[@]}"; do
if [ "$DB" == "$ACTIVE_DB" ]; then SELECTED=on; else SELECTED=off; fi
DB_LIST+=("$I" "$DB" "$SELECTED")
I=$(( I + 1 ))
done反斜杠和换行符是由shell解释的,而不是whiptail。不需要将它们放入数组中,所以我去掉了整个$SLASH变量。换行符无关紧要,所以再见echo ""。
最后,让我们运行whiptail。不再需要所有疯狂的引用和eval-ing。我们可以直接运行它,并在正确的位置扩展我们构建的数组。
whiptail --title "Select Database" --radiolist "Select Database:" 10 80 "$DB_COUNT" "${DB_LIST[@]}"还有更多的清理工作可以完成,但我认为这一天已经足够了。
https://stackoverflow.com/questions/55930117
复制相似问题