首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bash一次选择多个答案

bash一次选择多个答案
EN

Stack Overflow用户
提问于 2017-07-29 05:11:37
回答 3查看 3.8K关注 0票数 2

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

项目文件的内容:

代码语言:javascript
复制
cat 1
dog 1
pig 1
cherry 2
apple 2

基本脚本:

代码语言:javascript
复制
#!/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,并让它回答“你选择了:猫猪”

谢谢,

塔兹马尔

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-30 23:50:22

这就是我想出来的。这似乎像我想要的那样工作。我希望最后的输出用逗号分隔:

代码语言:javascript
复制
#!/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
票数 0
EN

Stack Overflow用户

发布于 2019-01-19 05:49:47

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

代码语言:javascript
复制
multiselect result "Option 1;Option 2;Option 3" "true;;true"

结果以数组的形式存储在变量中,其名称作为第一个参数提供。最后一个参数是可选的,用于默认选择某些选项。它看起来是这样的:

代码语言:javascript
复制
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[@]}")'
}
票数 5
EN

Stack Overflow用户

发布于 2017-07-29 05:54:33

您不能这样做,但您始终可以记录每个单独的选择:

代码语言:javascript
复制
#!/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

下面是一个交互示例:

代码语言:javascript
复制
$ ./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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45382472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档