bash一次选择多个答案

时间:2017-07-28 21:11:37

标签: bash select

我有一个名为item的平面文件,我想填充一个select,但我希望能够一次选择多个项目。

项目文件的内容:

cat 1
dog 1
pig 1
cherry 2
apple 2

基本脚本:

#!/bin/bash
PS3=$'\n\nSelect the animals you like: '
options=$(grep '1' items|grep -v '^#' |awk '{ print $1 }')

select choice in $options
do
  echo "you selected: $choice"
done

exit 0

现在流动的方式是我只能选择一个选项。我希望能够回答1,3或1 3并让它回应#34;你选择了:猫猪"

谢谢,

Tazmarine

3 个答案:

答案 0 :(得分:1)

你不能这样做,但你总是可以记录每个选择:

#!/bin/bash
PS3=$'\n\nSelect the animals you like: '
options=$(grep '1' items|grep -v '^#' |awk '{ print $1 }')

# Array for storing the user's choices
choices=()

select choice in $options Finished
do
  # Stop choosing on this option
  [[ $choice = Finished ]] && break
  # Append the choice to the array
  choices+=( "$choice" )
  echo "$choice, got it. Any others?"
done

# Write out each choice
printf "You selected the following: "
for choice in "${choices[@]}"
do
  printf "%s " "$choice"
done
printf '\n'

exit 0

以下是一个示例互动:

$ ./myscript
1) cat
2) dog
3) pig
4) Finished

Select the animals you like: 3
pig, got it. Any others?

Select the animals you like: 1
cat, got it. Any others?

Select the animals you like: 4
You selected the following: pig cat

如果您希望能够在同一行上撰写3 1,那么您必须使用echoread

创建自己的菜单循环

答案 1 :(得分:0)

这就是我想出的。这看起来像我想要的那样。我希望最终输出以逗号分隔:

#!/bin/bash

newarray=(all $(grep '1' items|grep -v '^#' |awk '{ print $1 }'))

options() {
num=0
for i in ${newarray[@]}; do
  echo "$num) $i"
  ((num++))
done
}

getanimal() {
while [[ "$show_clean" =~ [A-Za-z] || -z "$show_clean"  ]]; do
  echo "What animal do you like: "
  options
  read -p 'Enter number: ' show
  echo
  show_clean=$(echo $show|sed 's/[,.:;]/ /g')
  selected=$(\
  for s in $show_clean; do
    echo -n "\${newarray[${s}]},"
  done)
  selected_clean=$(echo $selected|sed 's/,$//')
done
eval echo "You selected $selected_clean"
}

getanimal

exit 0

答案 2 :(得分:0)

我可以提供一种使用不同选择提示样式的稍微不同的方法。这是一个bash功能,允许用户使用箭头键和空格键选择多个选项,然后按Enter确认。它具有类似菜单的感觉。我是在https://unix.stackexchange.com/a/415155的帮助下编写的。可以这样称呼:

multiselect result "Option 1;Option 2;Option 3" "true;;true"

结果以数组形式存储在变量中,该变量的名称为第一个参数。最后一个参数是可选的,默认情况下用于使某些选项处于选中状态。看起来像这样: example

function prompt_for_multiselect {

    # little helpers for terminal print control and key input
    ESC=$( printf "\033")
    cursor_blink_on()   { printf "$ESC[?25h"; }
    cursor_blink_off()  { printf "$ESC[?25l"; }
    cursor_to()         { printf "$ESC[$1;${2:-1}H"; }
    print_inactive()    { printf "$2   $1 "; }
    print_active()      { printf "$2  $ESC[7m $1 $ESC[27m"; }
    get_cursor_row()    { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; }
    key_input()         {
      local key
      IFS= read -rsn1 key 2>/dev/null >&2
      if [[ $key = ""      ]]; then echo enter; fi;
      if [[ $key = $'\x20' ]]; then echo space; fi;
      if [[ $key = $'\x1b' ]]; then
        read -rsn2 key
        if [[ $key = [A ]]; then echo up;    fi;
        if [[ $key = [B ]]; then echo down;  fi;
      fi 
    }
    toggle_option()    {
      local arr_name=$1
      eval "local arr=(\"\${${arr_name}[@]}\")"
      local option=$2
      if [[ ${arr[option]} == true ]]; then
        arr[option]=
      else
        arr[option]=true
      fi
      eval $arr_name='("${arr[@]}")'
    }

    local retval=$1
    local options
    local defaults

    IFS=';' read -r -a options <<< "$2"
    if [[ -z $3 ]]; then
      defaults=()
    else
      IFS=';' read -r -a defaults <<< "$3"
    fi
    local selected=()

    for ((i=0; i<${#options[@]}; i++)); do
      selected+=("${defaults[i]}")
      printf "\n"
    done

    # determine current screen position for overwriting the options
    local lastrow=`get_cursor_row`
    local startrow=$(($lastrow - ${#options[@]}))

    # ensure cursor and input echoing back on upon a ctrl+c during read -s
    trap "cursor_blink_on; stty echo; printf '\n'; exit" 2
    cursor_blink_off

    local active=0
    while true; do
        # print options by overwriting the last lines
        local idx=0
        for option in "${options[@]}"; do
            local prefix="[ ]"
            if [[ ${selected[idx]} == true ]]; then
              prefix="[x]"
            fi

            cursor_to $(($startrow + $idx))
            if [ $idx -eq $active ]; then
                print_active "$option" "$prefix"
            else
                print_inactive "$option" "$prefix"
            fi
            ((idx++))
        done

        # user key control
        case `key_input` in
            space)  toggle_option selected $active;;
            enter)  break;;
            up)     ((active--));
                    if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi;;
            down)   ((active++));
                    if [ $active -ge ${#options[@]} ]; then active=0; fi;;
        esac
    done

    # cursor position back to normal
    cursor_to $lastrow
    printf "\n"
    cursor_blink_on

    eval $retval='("${selected[@]}")'
}