bash shell 脚本多选
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11912167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
shell script multiple select
提问by wwwuser
I have a select statement that shows a list of dynamic files ($list). I'd like to be able to input "1, 2, 3" and it will have file 1, file 2, and file 3 be selected. How do I modify this select (maybe even a different structure is needed) to allow multiple options to be selected?
我有一个选择语句,显示动态文件列表 ($list)。我希望能够输入“1, 2, 3”,它将选择文件 1、文件 2 和文件 3。如何修改此选择(甚至可能需要不同的结构)以允许选择多个选项?
select option in $list; do
case $option in
* )
if [ "$option" ]; then
echo "Selected: " $option
break
else
echo "Invalid input. Try again."
fi;
esac
done
回答by AnBisw
This code doesn't use select, but does pretty much what you want-
此代码不使用select,但几乎可以满足您的需求-
#! /bin/bash
files=("file1" "file2" "file3" "file4" "Quit")
menuitems() {
echo "Avaliable options:"
for i in ${!files[@]}; do
printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${files[i]}"
done
[[ "$msg" ]] && echo "$msg"; :
}
prompt="Enter an option (enter again to uncheck, press RETURN when done): "
while menuitems && read -rp "$prompt" num && [[ "$num" ]]; do
[[ "$num" != *[![:digit:]]* ]] && (( num > 0 && num <= ${#files[@]} )) || {
msg="Invalid option: $num"; continue
}
if [ $num == ${#files[@]} ];then
exit
fi
((num--)); msg="${files[num]} was ${choices[num]:+un-}selected"
[[ "${choices[num]}" ]] && choices[num]="" || choices[num]="x"
done
printf "You selected"; msg=" nothing"
for i in ${!files[@]}; do
[[ "${choices[i]}" ]] && { printf " %s" "${files[i]}"; msg=""; }
done
echo "$msg"
Demo-
演示-
$ ./test.sh
Avaliable options:
1 ) file1
2 ) file2
3 ) file3
4 ) file4
5 ) Quit
Enter an option (enter again to uncheck, press RETURN when done): 1
Avaliable options:
1x) file1
2 ) file2
3 ) file3
4 ) file4
5 ) Quit
file1 was selected
Enter an option (enter again to uncheck, press RETURN when done): 2
Avaliable options:
1x) file1
2x) file2
3 ) file3
4 ) file4
5 ) Quit
file2 was selected
Enter an option (enter again to uncheck, press RETURN when done): 3
Avaliable options:
1x) file1
2x) file2
3x) file3
4 ) file4
5 ) Quit
file3 was selected
Enter an option (enter again to uncheck, press RETURN when done): 1
Avaliable options:
1 ) file1
2x) file2
3x) file3
4 ) file4
5 ) Quit
file1 was un-selected
Enter an option (enter again to uncheck, press RETURN when done):
You selected file2 file3
回答by Jaleks
As selectalways fills the variable REPLY, you could loop through your $listafterwards. (The VAR in $list$VAR is only filled, with single selection.)
e.g:
像select往常一样填充变量 REPLY,你可以在$list之后循环。(VAR in $list$VAR 仅填充,具有单一选择。)例如:
select ITEMS in $list; do
case $ITEMS in
* )
break
esac
done
# it $ITEMS is empty, but $REPLY not, we got multi selection
if [ -z "$ITEMS" ] && [ -n "$REPLY" ]; then
# add some spaces to begin and end for simpler checking below, regarding multi digit REPLY entries
REPLY_LIST=" $REPLY "
CNT=1
for ITEM in $list; do
if [[ "$REPLY_LIST" =~ " $CNT " ]]; then
ITEMS="$ITEMS $ITEM"
fi
CNT=$((CNT+1))
done
elif [ -z "$ITEMS" ]; then
echo nothing selected
exit
fi
echo "Selected: $ITEMS ($REPLY)"

