How do I prompt for Yes/No/Cancel input in a Linux shell script?

后端 未结 30 1698
不思量自难忘°
不思量自难忘° 2020-11-22 04:52

I want to pause input in a shell script, and prompt the user for choices.
The standard Yes, No, or Cancel type question.
How d

相关标签:
30条回答
  • 2020-11-22 05:24

    In response to others:

    You don't need to specify case in BASH4 just use the ',,' to make a var lowercase. Also I strongly dislike putting code inside of the read block, get the result and deal with it outside of the read block IMO. Also include a 'q' for quit IMO. Lastly why type 'yes' just use -n1 and have the press y.

    Example: user can press y/n and also q to just quit.

    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
    
    0 讨论(0)
  • 2020-11-22 05:26

    Use the read command:

    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
    

    and then all of the other stuff you need

    0 讨论(0)
  • 2020-11-22 05:26

    This solution reads a single character and calls a function on a yes response.

    read -p "Are you sure? (y/n) " -n 1
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        do_something      
    fi
    
    0 讨论(0)
  • 2020-11-22 05:26
    read -e -p "Enter your choice: " choice
    

    The -e option enables the user to edit the input using arrow keys.

    If you want to use a suggestion as input:

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

    -i option prints a suggestive input.

    0 讨论(0)
  • 2020-11-22 05:26

    I've used the case statement a couple of times in such a scenario, using the case statment is a good way to go about it. A while loop, that ecapsulates the case block, that utilizes a boolean condition can be implemented in order to hold even more control of the program, and fulfill many other requirements. After the all the conditions have been met, a break can be used which will pass control back to the main part of the program. Also, to meet other conditions, of course conditional statements can be added to accompany the control structures: case statement and possible while loop.

    Example of using a case statement to fulfill your request

    #! /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
    
    0 讨论(0)
  • 2020-11-22 05:27

    Single keypress only

    Here's a longer, but reusable and modular approach:

    • Returns 0=yes and 1=no
    • No pressing enter required - just a single character
    • Can press enter to accept the default choice
    • Can disable default choice to force a selection
    • Works for both zsh and bash.

    Defaulting to "no" when pressing enter

    Note that the N is capitalsed. Here enter is pressed, accepting the default:

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

    Also note, that [y/N]? was automatically appended. The default "no" is accepted, so nothing is echoed.

    Re-prompt until a valid response is given:

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

    Defaulting to "yes" when pressing enter

    Note that the Y is capitalised:

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

    Above, I just pressed enter, so the command ran.

    No default on enter - require y or 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
    

    Here, 1 or false was returned. Note that with this lower-level function you'll need to provide your own [y/n]? prompt.

    Code

    # 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
    }
    
    0 讨论(0)
提交回复
热议问题