2012-08-11 103 views
2

我有一个select语句显示动态文件列表($ list)。我希望能够输入“1,2,3”,并且会选择文件1,文件2和文件3。我如何修改这个选择(甚至可能需要不同的结构)以允许选择多个选项?shell script multiple select

select option in $list; do 
     case $option in 
      *) 
       if [ "$option" ]; then 
        echo "Selected: " $option 
        break 
       else 
        echo "Invalid input. Try again." 
       fi; 
     esac 
    done 
+0

你只想补充的情况下'1)','2)','3)'?或者你需要更复杂的东西? – 2012-08-11 05:43:07

+0

它会更复杂。 $ list包含特定目录中的所有文件。添加和删​​除文件到目录将改变案件号码。我宁愿每次都不更新shell脚本。 – wwwuser 2012-08-11 05:46:12

+2

也许你应该考虑另一种攻击计划,或者使用“对话”或者更复杂的语言。 – 2012-08-11 06:21:42

回答

5

这个代码不使用select,但确实差不多就是你want-

#! /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" 

人口统计学

$ ./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 
+0

当您提示“输入选项”时,我希望能够输入:“1,2,3”,并输出“您选择了file1,file2,file3”。您的代码只允许您一次选择一个选项,然后再次提示用户。我正在寻找一个提示,并能够输入多个选项。 – wwwuser 2012-08-12 04:11:19

+0

如果你正在寻找特定的需求,那么我认为你的对话更好。您建议“1,2,3”的输入可能太容易出错,即用户可能输入“123”,“1,23”,“111”,“1 2 3”等,代码将会花更多的时间来解析和验证,而不是做实际的工作。您可能最终会创建一个难以阅读,理解和维护的巨大正则表达式“陷阱”。 – Annjawn 2012-08-12 05:40:49

0

由于select总是充满变数答复,你可以循环之后通过您的$list。 (该VAR in $list $ VAR只装满,单选择。) e.g:

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)"