代码之家  ›  专栏  ›  技术社区  ›  Myrddin Emrys

如何在Linuxshell脚本中提示“是/否/取消”输入?

  •  1218
  • Myrddin Emrys  · 技术社区  · 16 年前

    我想暂停shell脚本中的输入,并提示用户选择。标准的“是、否或取消”类型的问题。如何在典型的bash提示中完成这一点?

    28 回复  |  直到 16 年前
        1
  •  1372
  •   Spooky Muscothym    7 年前

    在shell提示下获取用户输入的最简单和最广泛可用的方法是 read 命令。说明其用途的最佳方法是简单演示:

    while true; do
        read -p "Do you wish to install this program?" yn
        case $yn in
            [Yy]* ) make install; break;;
            [Nn]* ) exit;;
            * ) echo "Please answer yes or no.";;
        esac
    done
    

    史蒂文·赫维格指出的另一种方法是巴什的 select 命令。下面是使用 选择 :

    echo "Do you wish to install this program?"
    select yn in "Yes" "No"; do
        case $yn in
            Yes ) make install; break;;
            No ) exit;;
        esac
    done
    

    选择 您不需要清理输入–它会显示可用的选项,并键入与您的选择相对应的数字。它也会自动循环,因此不需要 while true 循环以在提供无效输入时重试。

    另外,请查看 excellent answer F. Hauri。

        2
  •  426
  •   Myrddin Emrys    6 年前

    一个普通问题至少有五个答案。

    取决于

    • 兼容:可以在通用的差系统上工作 环境
    • 特定:使用所谓的 巴什教

    如果你想要

    • 简单的“在线”问题/答案(通用解决方案)
    • 格式很好的接口,比如 或使用libgtk或libqt进行更多图形化…
    • 使用强大的阅读线历史记录功能

    1。POSIX通用解决方案

    你可以用 read 命令,后跟 if ... then ... else :

    echo -n "Is this a good question (y/n)? "
    read answer
    

    # if echo "$answer" | grep -iq "^y" ;then
    

    if [ "$answer" != "${answer#[Yy]}" ] ;then
        echo Yes
    else
        echo No
    fi
    

    (感谢 Adam Katz's comment :将上面的测试替换为更便携且避免使用一个分叉的测试:)

    POSIX,但单键功能

    但是如果你不想让用户点击 返回 ,你可以写:

    ( 编辑: 正如@jonathanlefler所说, 节约 Stty的配置可能比简单地强迫他们 理智的 )

    echo -n "Is this a good question (y/n)? "
    old_stty_cfg=$(stty -g)
    stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
    if echo "$answer" | grep -iq "^y" ;then
        echo Yes
    else
        echo No
    fi
    

    注: 这是在 , , , !

    相同,但明确等待 Y n :

    #/bin/sh
    echo -n "Is this a good question (y/n)? "
    old_stty_cfg=$(stty -g)
    stty raw -echo
    answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
    stty $old_stty_cfg
    if echo "$answer" | grep -iq "^y" ;then
        echo Yes
    else
        echo No
    fi
    

    使用专用工具

    有许多工具是用 libncurses , libgtk , libqt 或其他图形库。例如,使用 whiptail :

    if whiptail --yesno "Is this a good question" 20 60 ;then
        echo Yes
    else
        echo No
    fi
    

    根据您的系统,您可能需要更换 鞭梢 使用另一个类似的工具:

    dialog --yesno "Is this a good question" 20 60 && echo Yes
    
    gdialog --yesno "Is this a good question" 20 60 && echo Yes
    
    kdialog --yesno "Is this a good question" 20 60 && echo Yes
    

    哪里 20 是以行数和为单位的对话框高度 60 是对话框的宽度。这些工具都有 几乎相同 语法。

    DIALOG=whiptail
    if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
    if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
    ...
    $DIALOG --yesno ...
    

    2。bash特定的解决方案

    基本的 在线 方法

    read -p "Is this a good question (y/n)? " answer
    case ${answer:0:1} in
        y|Y )
            echo Yes
        ;;
        * )
            echo No
        ;;
    esac
    

    我更喜欢使用 case 所以我可以测试 yes | ja | si | oui 如果需要…

    在线 具有 单键 特征

    在bash下,我们可以为 阅读 命令:

    read -n 1 -p "Is this a good question (y/n)? " answer
    

    抨击之下, 阅读 命令接受 超时 参数,可能有用。

    read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
    [ -z "$answer" ] && answer="Yes"  # if 'yes' have to be default choice
    

    一些窍门 专用工具

    更复杂的对话框,不仅仅是简单的 yes - no 用途:

    dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
    

    进度条:

    dialog --gauge "Filling the tank" 20 60 0 < <(
        for i in {1..100};do
            printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
            sleep .033
        done
    ) 
    

    小演示:

    #!/bin/sh
    while true ;do
        [ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
        DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
                whiptail       "dialog boxes from shell scripts" >/dev/tty \
                dialog         "dialog boxes from shell with ncurses" \
                gdialog        "dialog boxes from shell with Gtk" \
                kdialog        "dialog boxes from shell with Kde" ) || exit
        clear;echo "Choosed: $DIALOG."
        for i in `seq 1 100`;do
            date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
            sleep .0125
          done | $DIALOG --gauge "Filling the tank" 20 60 0
        $DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
        sleep 3
        if $DIALOG --yesno  "Do you like this demo?" 20 60 ;then
            AnsYesNo=Yes; else AnsYesNo=No; fi
        AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
        AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
        $DIALOG --textbox /etc/motd 20 60
        AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
            Correct "This demo is useful"        off \
            Fun        "This demo is nice"        off \
            Strong        "This demo is complex"        on 2>&1 >/dev/tty)
        AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
            " -1" "Downgrade this answer"        off \
            "  0" "Not do anything"                on \
            " +1" "Upgrade this anser"        off 2>&1 >/dev/tty)
        out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
        $DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
      done
    

    更多样本?看一看 Using whiptail for choosing USB device USB removable storage selector: USBKeyChooser

    5。使用readline的历史记录

    例子:

    #!/bin/bash
    
    set -i
    HISTFILE=~/.myscript.history
    history -c
    history -r
    
    myread() {
        read -e -p '> ' $1
        history -s ${!1}
    }
    trap 'history -a;exit' 0 1 2 3 6
    
    while myread line;do
        case ${line%% *} in
            exit )  break ;;
            *    )  echo "Doing something with '$line'" ;;
          esac
      done
    

    这将创建一个文件 .myscript.history 在你 $HOME 目录,不能使用readline的history命令,例如 向上 , 向下 , Ctrl键 + R 以及其他。

        3
  •  340
  •   Your Common Sense    10 年前
    echo "Please enter some input: "
    read input_variable
    echo "You entered: $input_variable"
    
        4
  •  145
  •   yPhil Erdogan Oksuz    6 年前

    您可以使用内置的 read 命令;使用 -p 向用户提示问题的选项。

    从bash4开始,现在可以使用 -i 为了给出答案,用户只需按 return 进入:

    read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
    echo $FILEPATH
    

    (但记住使用“readline”选项 -e 允许使用箭头键进行行编辑)

    如果需要“是/否”逻辑,可以这样做:

    read -e -p "
    List the content of your home dir ? [Y/n] " YN
    
    [[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
    
        5
  •  100
  •   Steven Huwig    16 年前

    巴什有 select 为此目的。

    select result in Yes No Cancel
    do
        echo $result
    done
    
        6
  •  54
  •   serg    14 年前
    read -p "Are you alright? (y/n) " RESP
    if [ "$RESP" = "y" ]; then
      echo "Glad to hear it"
    else
      echo "You need more bash programming"
    fi
    
        7
  •  31
  •   mpen    12 年前

    以下是我整理的:

    #!/bin/sh
    
    promptyn () {
        while true; do
            read -p "$1 " yn
            case $yn in
                [Yy]* ) return 0;;
                [Nn]* ) return 1;;
                * ) echo "Please answer yes or no.";;
            esac
        done
    }
    
    if promptyn "is the sky blue?"; then
        echo "yes"
    else
        echo "no"
    fi
    

    我是个初学者,所以拿着这个加一点盐,但它似乎有效。

        8
  •  28
  •   Benjamin W.    8 年前
    inquire ()  {
      echo  -n "$1 [y/n]? "
      read answer
      finish="-1"
      while [ "$finish" = '-1' ]
      do
        finish="1"
        if [ "$answer" = '' ];
        then
          answer=""
        else
          case $answer in
            y | Y | yes | YES ) answer="y";;
            n | N | no | NO ) answer="n";;
            *) finish="-1";
               echo -n 'Invalid response -- please reenter:';
               read answer;;
           esac
        fi
      done
    }
    
    ... other stuff
    
    inquire "Install now?"
    
    ...
    
        9
  •  25
  •   oHo Denis Tulskiy    7 年前

    你想要:

    • bash内置命令(即便携式)
    • 检查TTY
    • 默认答案
    • 超时
    • 彩色问题

    片断

    do_xxxx=y                      # In batch mode => Default is Yes
    [[ -t 0 ]] &&                  # If TTY => Prompt the question
    read -n 1 -p $'\e[1;32m
    Do xxxx? (Y/n)\e[0m ' do_xxxx  # Store the answer in $do_xxxx
    if [[ $do_xxxx =~ ^(y|Y|)$ ]]  # Do if 'y' or 'Y' or empty
    then
        xxxx
    fi
    

    解释

    • [[ -t 0 ]] && read ... =>调用命令 read 如果TTY
    • read -n 1 =>等待一个字符
    • $'\e[1;32m ... \e[0m ' =>打印为绿色
      (绿色很好,因为白色/黑色背景都可读)
    • [[ $do_xxxx =~ ^(y|Y|)$ ]] =>bash正则表达式

    超时=>默认答案为否

    do_xxxx=y
    [[ -t 0 ]] && {                   # Timeout 5 seconds (read -t 5)
    read -t 5 -n 1 -p $'\e[1;32m
    Do xxxx? (Y/n)\e[0m ' do_xxxx ||  # read 'fails' on timeout
    do_xxxx=n ; }                     # Timeout => answer No
    if [[ $do_xxxx =~ ^(y|Y|)$ ]]
    then
        xxxx
    fi
    
        10
  •  21
  •   nbro kai    8 年前

    用最少的行数实现这一点的最简单方法如下:

    read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
    
    if [ "$CONDITION" == "y" ]; then
       # do something here!
    fi
    

    这个 if 只是一个例子:如何处理这个变量取决于您。

        11
  •  17
  •   Dennis    11 年前

    此解决方案读取单个字符并在Yes响应上调用函数。

    read -p "Are you sure? (y/n) " -n 1
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        do_something      
    fi
    
        12
  •  17
  •   nbro kai    8 年前

    使用 read 命令:

    echo Would you like to install? "(Y or N)"
    
    read x
    
    # now check if $x is "y"
    if [ "$x" = "y" ]; then
        # do something here!
    fi
    

    然后所有你需要的东西

        13
  •  12
  •   Jahid Ramsy de Vos    10 年前
    read -e -p "Enter your choice: " choice
    

    这个 -e 选项允许用户使用箭头键编辑输入。

    如果要使用建议作为输入:

    read -e -i "yes" -p "Enter your choice: " choice
    

    -i 选项打印提示性输入。

        14
  •  9
  •   user9869932    11 年前

    很抱歉在这么旧的帖子上发帖。几周前,我遇到了一个类似的问题,在我的情况下,我需要一个解决方案,它也适用于在线安装程序脚本,例如: curl -Ss https://raw.github.com/_____/installer.sh | bash

    使用 read yesno < /dev/tty 对我来说很好:

    echo -n "These files will be uploaded. Is this ok? (y/n) "
    read yesno < /dev/tty
    
    if [ "x$yesno" = "xy" ];then
    
       # Yes
    else
    
       # No
    fi
    

    希望这能帮助别人。

        15
  •  8
  •   Thorsten Staerk    11 年前

    要获得像inputbox这样的漂亮的ncurse,请使用命令 对话 这样地:

    #!/bin/bash
    if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
    # message box will have the size 25x6 characters
    then 
        echo "Let's do something risky"
        # do something risky
    else 
        echo "Let's stay boring"
    fi
    

    默认情况下,至少在SUSE Linux上安装对话框包。

        16
  •  6
  •   Tom Hale    6 年前

    仅限单按键

    这里有一个较长但可重用的模块化方法:

    • 退换商品 0 =是的 1 =没有
    • 不需要按Enter键-只需要一个字符
    • 可以按 进入 接受默认选项
    • 可以禁用默认选项以强制选择
    • 为双方工作 zsh bash .

    按Enter时默认为“否”

    请注意 N 是资本化的。在此按Enter,接受默认值:

    $ confirm "Show dangerous command" && echo "rm *"
    Show dangerous command [y/N]?
    

    还要注意的是 [y/N]? 已自动附加。 默认的“否”被接受,因此没有任何响应。

    重新提示直到给出有效响应:

    $ confirm "Show dangerous command" && echo "rm *"
    Show dangerous command [y/N]? X
    Show dangerous command [y/N]? y
    rm *
    

    按Enter时默认为“是”

    请注意 Y 资本化:

    $ confirm_yes "Show dangerous command" && echo "rm *"
    Show dangerous command [Y/n]?
    rm *
    

    上面,我刚按下Enter,命令就运行了。

    无默认 进入 -要求 y n

    $ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
    Here you cannot press enter. Do you like this [y/n]? k
    Here you cannot press enter. Do you like this [y/n]?
    Here you cannot press enter. Do you like this [y/n]? n
    $ echo $?
    1
    

    在这里, 或者返回了false。请注意,使用这个较低级别的功能,您需要提供自己的 [y/n]? 提示。

    代码

    # Read a single char from /dev/tty, prompting with "$*"
    # Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
    # See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
    function get_keypress {
      local REPLY IFS=
      >/dev/tty printf '%s' "$*"
      [[ $ZSH_VERSION ]] && read -rk1  # Use -u0 to read from STDIN
      # See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
      [[ $BASH_VERSION ]] && </dev/tty read -rn1
      printf '%s' "$REPLY"
    }
    
    # Get a y/n from the user, return yes=0, no=1 enter=$2
    # Prompt using $1.
    # If set, return $2 on pressing enter, useful for cancel or defualting
    function get_yes_keypress {
      local prompt="${1:-Are you sure [y/n]? }"
      local enter_return=$2
      local REPLY
      # [[ ! $prompt ]] && prompt="[y/n]? "
      while REPLY=$(get_keypress "$prompt"); do
        [[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
        case "$REPLY" in
          Y|y)  return 0;;
          N|n)  return 1;;
          '')   [[ $enter_return ]] && return "$enter_return"
        esac
      done
    }
    
    # Credit: http://unix.stackexchange.com/a/14444/143394
    # Prompt to confirm, defaulting to NO on <enter>
    # Usage: confirm "Dangerous. Are you sure?" && rm *
    function confirm {
      local prompt="${*:-Are you sure} [y/N]? "
      get_yes_keypress "$prompt" 1
    }    
    
    # Prompt to confirm, defaulting to YES on <enter>
    function confirm_yes {
      local prompt="${*:-Are you sure} [Y/n]? "
      get_yes_keypress "$prompt" 0
    }
    
        17
  •  4
  •   Ernest A    11 年前

    多选版本:

    ask () {                        # $1=question $2=options
        # set REPLY
        # options: x=..|y=..
        while $(true); do
            printf '%s [%s] ' "$1" "$2"
            stty cbreak
            REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
            stty -cbreak
            test "$REPLY" != "$(printf '\n')" && printf '\n'
            (
                IFS='|'
                for o in $2; do
                    if [ "$REPLY" = "${o%%=*}" ]; then
                        printf '\n'
                        break
                    fi
                done
            ) | grep ^ > /dev/null && return
        done
    }
    

    例子:

    $ ask 'continue?' 'y=yes|n=no|m=maybe'
    continue? [y=yes|n=no|m=maybe] g
    continue? [y=yes|n=no|m=maybe] k
    continue? [y=yes|n=no|m=maybe] y
    $
    

    它将设置 REPLY y (在脚本中)。

        18
  •  4
  •   poxtron    10 年前

    受@mark和@myrddin答案的启发,我创建了一个通用提示的函数

    uniprompt(){
        while true; do
            echo -e "$1\c"
            read opt
            array=($2)
            case "${array[@]}" in  *"$opt"*) eval "$3=$opt";return 0;; esac
            echo -e "$opt is not a correct value\n"
        done
    }
    

    这样使用:

    unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
    echo "$selection"
    
        19
  •  4
  •   Yokai    8 年前

    我注意到,没有人发布一个答案,显示了这样简单的用户输入的多行回音菜单,所以下面是我的步骤:

    #!/bin/bash
    
    function ask_user() {    
    
    echo -e "
    #~~~~~~~~~~~~#
    | 1.) Yes    |
    | 2.) No     |
    | 3.) Quit   |
    #~~~~~~~~~~~~#\n"
    
    read -e -p "Select 1: " choice
    
    if [ "$choice" == "1" ]; then
    
        do_something
    
    elif [ "$choice" == "2" ]; then
    
        do_something_else
    
    elif [ "$choice" == "3" ]; then
    
        clear && exit 0
    
    else
    
        echo "Please select 1, 2, or 3." && sleep 3
        clear && ask_user
    
    fi
    }
    
    ask_user
    

    这个方法被贴出来,希望有人能发现它有用,节省时间。

        20
  •  3
  •   brasofilo Gary    10 年前

    我建议你 use dialog

    Linux Apprentice: Improve Bash Shell Scripts Using Dialog

    dialog命令允许在shell脚本中使用窗口框,以使它们的使用更加交互式。

    它简单易用,还有一个GNOME版本叫做gDialog,它使用完全相同的参数,但在X上显示了它的GUI样式。

        21
  •  3
  •   Joshua Goldberg    10 年前

    一个简单的方法是 xargs -p 或GNU parallel --interactive .

    我对此比较喜欢xargs的行为,因为它像其他交互的unix命令一样在提示后立即执行每个命令,而不是收集在末尾运行的yes。(您可以在完成所需的任务后按ctrl-c。)

    例如。,

    echo *.xml | xargs -p -n 1 -J {} mv {} backup/
    
        22
  •  3
  •   Alexander Löfqvist    9 年前

    更一般的是:

    function menu(){
        title="Question time"
        prompt="Select:"
        options=("Yes" "No" "Maybe")
        echo "$title"
        PS3="$prompt"
        select opt in "${options[@]}" "Quit/Cancel"; do
            case "$REPLY" in
                1 ) echo "You picked $opt which is option $REPLY";;
                2 ) echo "You picked $opt which is option $REPLY";;
                3 ) echo "You picked $opt which is option $REPLY";;
                $(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
                *) echo "Invalid option. Try another one.";continue;;
             esac
         done
         return
    }
    
        23
  •  3
  •   Walter A    6 年前

    您可以使用默认值 REPLY 在一 read ,转换为小写并与表达式中的一组变量进行比较。
    脚本还支持 ja / si / qui

    read -rp "Do you want a demo? [y/n/c] "
    
    [[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }
    
    if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
       echo "Positive"
    fi
    
        24
  •  2
  •   jlettvin    11 年前
    yn() {
      if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
      then eval $1;
      else eval $2;
      fi }
    yn 'echo yes' 'echo no'
    yn 'echo absent no function works too!'
    
        25
  •  2
  •   Myrddin Emrys    10 年前

    作为单行命令的朋友,我使用了以下命令:

    while [ -z $prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) prompt=true; break;; n|N ) exit 0;; esac; done; prompt=;
    

    写的很长,它的工作原理如下:

    while [ -z $prompt ];
      do read -p "Continue (y/n)?" choice;
      case "$choice" in
        y|Y ) prompt=true; break;;
        n|N ) exit 0;;
      esac;
    done;
    prompt=;
    
        26
  •  2
  •   oOpSgEo    8 年前

    我已经用过了 case 在这种情况下,多次声明,使用case语句是一种很好的方法。一 while 循环,它将 案例 块,利用布尔条件可以实现,以保持对程序的更多控制,并满足许多其他要求。在所有条件都满足之后,a break 可用于将控制权传递回程序的主要部分。此外,为了满足其他条件,当然可以在控制结构中添加条件语句: 案例 陈述和可能 虽然 循环。

    使用的示例 案例 满足您要求的声明

    #! /bin/sh 
    
    # For potential users of BSD, or other systems who do not
    # have a bash binary located in /bin the script will be directed to
    # a bourne-shell, e.g. /bin/sh
    
    # NOTE: It would seem best for handling user entry errors or
    # exceptions, to put the decision required by the input 
    # of the prompt in a case statement (case control structure), 
    
    echo Would you like us to perform the option: "(Y|N)"
    
    read inPut
    
    case $inPut in
        # echoing a command encapsulated by 
        # backticks (``) executes the command
        "Y") echo `Do something crazy`
        ;;
        # depending on the scenario, execute the other option
        # or leave as default
        "N") echo `execute another option`
        ;;
    esac
    
    exit
    
        27
  •  1
  •   Mike Q    7 年前

    回应他人:

    您不需要在bash4中指定case,只需使用“,,”将var变为小写。另外,我非常不喜欢把代码放在读取块内,得到结果并在读取块IMO之外处理它。还包括退出IMO的“q”。最后,为什么键入“yes”只使用-n1并按下y。

    示例:用户可以按Y/N和Q退出。

    ans=''
    while true; do
        read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
        case ${ans,,} in
            y|n|q) break;;
            *) echo "Answer y for yes / n for no  or q for quit.";;
        esac
    done
    
    echo -e "\nAnswer = $ans"
    
    if [[ "${ans,,}" == "q" ]] ; then
            echo "OK Quitting, we will assume that he is"
            exit 0
    fi
    
    if [[ "${ans,,}" == "y" ]] ; then
            echo "MikeQ is the greatest!!"
    else
            echo "No? MikeQ is not the greatest?"
    fi
    
        28
  •  0
  •   Eduardo Cuomo Sajjad Ali Khan    7 年前

    是/否/取消

    功能

    #!/usr/bin/env bash
    @confirm() {
      local message="$*"
      local result=''
    
      echo -n "> $message (Yes/No/Cancel) " >&2
    
      while [ -z "$result" ] ; do
        read -s -n 1 choice
        case "$choice" in
          y|Y ) result='Y' ;;
          n|N ) result='N' ;;
          c|C ) result='C' ;;
        esac
      done
    
      echo $result
    }
    

    用法

    case $(@confirm 'Confirm?') in
      Y ) echo "Yes" ;;
      N ) echo "No" ;;
      C ) echo "Cancel" ;;
    esac
    

    用干净的用户输入确认

    功能

    #!/usr/bin/env bash
    @confirm() {
      local message="$*"
      local result=3
    
      echo -n "> $message (y/n) " >&2
    
      while [[ $result -gt 1 ]] ; do
        read -s -n 1 choice
        case "$choice" in
          y|Y ) result=0 ;;
          n|N ) result=1 ;;
        esac
      done
    
      return $result
    }
    

    用法

    if @confirm 'Confirm?' ; then
      echo "Yes"
    else
      echo "No"
    fi