Jak Mogę prosić o wejście tak/nie / Anuluj w skrypcie powłoki Linuksa?

Chcę wstrzymać wprowadzanie w skrypcie powłoki i poprosić Użytkownika o wybór. Standardowe pytanie typu "tak, nie lub Anuluj". Jak mogę to osiągnąć w typowym monicie bash?

Author: Brandon Rhodes, 2008-10-22

27 answers

Najprostszą i najpowszechniej dostępną metodą uzyskiwania danych przez użytkownika w wierszu polecenia powłoki jest read dowództwo. Najlepszym sposobem zilustrowania jego użycia jest prosta demonstracja:

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
Inną metodą, wskazaną przez Stevena Huwiga, jest metoda Basha select dowództwo. Oto ten sam przykład użycia 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

Z select nie musisz dezynfekować wejścia-wyświetla dostępne opcje i wpisujesz numer odpowiadający wybranemu przez Ciebie. Również pętle automatycznie, więc nie ma potrzeby, aby pętla while true ponawiała próbę, jeśli poda nieprawidłowe dane wejściowe.

Również, proszę sprawdzić doskonała odpowiedź F. Hauri.

 1306
Author: Myrddin Emrys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-02 06:11:49

Co najmniej pięć odpowiedzi na jedno ogólne Pytanie.

W zależności od

  • Standard posix może pracować na słabych systemach ze środowiskami generic shell
  • bash specific: using so called bashisms

I jeśli chcesz

    [[36]} proste" w linii " pytanie / odpowiedź (rozwiązania ogólne)
  • dość sformatowane interfejsy, jak ncurses lub bardziej graficzne przy użyciu libgtk lub libqt...
  • użyj potężnej funkcji historii readline

1. POSIX generic solutions

Możesz użyć komendy read, po której następuje 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

(Dzięki komentarzowi Adama Katza : zastąpiłem powyższy test na taki, który jest bardziej przenośny i unika jednego widelca:)

POSIX, ale funkcja pojedynczego klucza

Ale jeśli nie chcesz, aby użytkownik musiał uderzyć Return , możesz można napisać:

(Edited: jak słusznie sugeruje @ JonathanLeffler, zapisanie konfiguracji stty może być lepsze niż zwykłe zmuszenie ich do sane.)

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

Uwaga: to zostało przetestowane pod sh, bash, ksh, dash i busybox !

To samo, ale czekam wprost na y lub 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

Za pomocą dedykowanych narzędzi

Istnieje wiele narzędzi, które zostały zbudowane przy użyciu libncurses, libgtk, libqt lub innych bibliotek graficznych. Na przykład, używając whiptail:

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

W zależności od systemu, może być konieczne zastąpienie whiptail innym podobnym narzędziem:

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

Gdzie 20 jest wysokością okna dialogowego w liczbie linii, a {[23] } jest szerokością okna dialogowego. Wszystkie te narzędzia mają podobną składnię .

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

2. Rozwiązania specyficzne dla Bash

Basic in line method

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

Wolę używać case więc mogę nawet przetestować yes | ja | si | oui w razie potrzeby...

in line with single key feature

Pod bashem możemy określić długość zamierzonego wejścia dla polecenia read:

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

W bash polecenie read przyjmuje parametr timeout , który może być przydatny.

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

Kilka sztuczek dla dedykowanych narzędzi

Bardziej wyrafinowane okna dialogowe, poza prostymi yes - no cele:

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

Pasek postępu:

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
) 

Małe demo:

#!/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
Więcej próbki? W tym celu należy wybrać urządzenie USB, a następnie wybrać opcję USB removable storage selector: USBKeyChooser

5. Korzystanie z historii readline

Przykład:

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

Spowoduje to utworzenie pliku .myscript.history w katalogu $HOME, niż można użyć poleceń historii readline, takich jak w górę, Down , Ctrl+r i inni.

 392
Author: F. Hauri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 14:14:00
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
 335
Author: Pistos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-28 20:01:34

Możesz użyć wbudowanego polecenia read; użyj opcji -p, aby zapytać użytkownika o pytanie.

Od BASH4 możesz teraz użyć -i, aby zasugerować odpowiedź, więc użytkownik musi nacisnąć return, aby ją wprowadzić:

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

(ale pamiętaj, aby użyć opcji "readline" -e, aby umożliwić edycję linii za pomocą klawiszy strzałek)

Jeśli chcesz logiki "tak / nie", możesz zrobić coś takiego:

read -e -p "
List the content of your home dir ? [Y/n] " YN

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
 129
Author: yPhil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-19 17:03:00

Bash ma select w tym celu.

select result in Yes No Cancel
do
    echo $result
done
 98
Author: Steven Huwig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-22 18:14:01
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
 53
Author: serg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-03 13:23:04

Oto coś, co poskładałem:

#!/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
Jestem początkujący, więc weź to z przymrużeniem oka, ale wydaje się, że działa.
 30
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-30 17:59:18
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?"

...
 24
Author: SumoRunner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 15:01:15

Chcesz:

  • polecenia wbudowane w Bash (np. portable)
  • Sprawdź TTY
  • domyślna odpowiedź
  • Timeout
  • kolorowe pytanie

Snippet

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

Objaśnienia

  • [[ -t 0 ]] && read ... => Call command read if TTY
  • read -n 1 = > Poczekaj na jeden znak
  • $'\e[1;32m ... \e[0m ' => Drukuj na Zielono
    (zielony jest w porządku, ponieważ czytelny zarówno na białym/czarnym tle)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => Bash regex

Timeout => Domyślna odpowiedź to nie

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
 23
Author: olibre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 10:36:50

Najprostszym sposobem na osiągnięcie tego przy jak najmniejszej liczbie linii jest:

read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;

if [ "$CONDITION" == "y" ]; then
   # do something here!
fi

if jest tylko przykładem: to od Ciebie zależy, jak obsłużyć tę zmienną.

 20
Author: Apurv Nerlekar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-14 16:06:39

Użyj polecenia 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

And then all of the other stuff you need

 17
Author: ThatLinuxGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-14 16:07:42

To rozwiązanie odczytuje pojedynczy znak i wywołuje funkcję w odpowiedzi tak.

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi
 16
Author: Dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-15 07:04:18
read -e -p "Enter your choice: " choice

Opcja -e umożliwia użytkownikowi edycję danych wejściowych za pomocą klawiszy strzałek.

Jeśli chcesz użyć sugestii jako wejścia:

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

-i opcja wyświetla sugestywne dane wejściowe.

 12
Author: Jahid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-19 00:37:02

Przepraszam za zamieszczenie na tak starym poście. Kilka tygodni temu borykałem się z podobnym problemem, w moim przypadku potrzebowałem rozwiązania, które również działało w ramach instalatora internetowego-skryptu, np: curl -Ss https://raw.github.com/_____/installer.sh | bash

Using read yesno < /dev/tty works fine for me:

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
Mam nadzieję, że to komuś pomoże.
 9
Author: xyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-22 11:07:15

Aby uzyskać ładny inputbox podobny do ncurses użyj polecenia dialogi Tak:

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

Pakiet dialogowy jest domyślnie instalowany przynajmniej z SUSE Linux.

 7
Author: Thorsten Staerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-06 11:40:47

Wersja wielokrotnego wyboru:

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
}

Przykład:

$ 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
$

Ustawia REPLY na y (wewnątrz skryptu).

 4
Author: Ernest A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-28 17:50:02

Zainspirowany odpowiedziami @ Mark i @ Myrddin stworzyłem tę funkcję dla uniwersalnego wiersza

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
}

Użyj go tak:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
 4
Author: poxtron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-08 00:40:48

Proponuję użyć okna dialogowego ...

Linux Apprentice: Ulepszanie Skryptów Powłoki Bash Za Pomocą Okna Dialogowego

Polecenie dialog umożliwia użycie okienek w skryptach powłoki, aby uczynić ich użycie bardziej interaktywnym.

Jest prosty i łatwy w użyciu, istnieje również wersja gnome o nazwie gdialog, która pobiera dokładnie te same parametry, ale wyświetla styl GUI Na X.

 3
Author: Osama Al-Maadeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-09 23:19:57

Jednym z prostych sposobów na to jest xargs -p lub gnu parallel --interactive.

Bardziej podoba mi się zachowanie xargs, ponieważ wykonuje każde polecenie natychmiast po znaku zachęty, jak inne interaktywne polecenia uniksowe, zamiast zbierać yesses do uruchomienia na końcu. (Możesz Ctrl-C po przejściu przez te, które chciałeś.)

Np.,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/
 3
Author: Joshua Goldberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 19:30:25

Bardziej ogólne byłoby:

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
}
 3
Author: Alexander Löfqvist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-29 11:39:09

Tylko jedna klawiatura

Oto dłuższe, ale wielokrotnego użytku i modułowe podejście:]}
  • zwraca 0=Tak i 1 = Nie
  • nie jest wymagane naciśnięcie klawisza enter - tylko jeden znak
  • można nacisnąć enter , aby zaakceptować domyślny wybór
  • Można wyłączyć domyślny wybór, aby wymusić wybór]}
  • Działa zarówno dla zsh jak i bash.

Domyślnie " nie " po naciśnięciu enter

Zauważ, że N jest pisana wielkimi literami. Proszę. klawisz enter Jest wciśnięty, akceptując wartość domyślną:

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

Zauważ również, że [y/N]? została automatycznie dołączona. Domyślne " nie " jest akceptowane, więc nic nie jest echem.

Re-prompt dopóki nie zostanie podana prawidłowa odpowiedź:

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

Domyślnie " tak " po naciśnięciu enter

Zauważ, że Y jest pisane wielkimi literami:

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

Powyżej, po prostu wcisnąłem enter, więc Komenda uruchomiła się.

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

Tutaj, 1 lub false został zwrócony. Zauważ, że dzięki tej funkcji niższego poziomu będziesz musiał podać swój własny znak zachęty [y/n]?.

Kod

# 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
}
 3
Author: Tom Hale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-01 07:25:13
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!'
 2
Author: jlettvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-24 03:38:54

Jako przyjaciel polecenia jednowierszowego użyłem następującego:

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=;

Napisany longform, działa tak:

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=;
 2
Author: ccDict,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-05 06:37:02

Użyłem case wypowiedzenia kilka razy w takim scenariuszu, użycie określenia przypadku jest dobrym sposobem na to. Pętla while, która ecapsuluje blok case, który wykorzystuje warunek logiczny, może być zaimplementowana w celu uzyskania jeszcze większej kontroli nad programem i spełnienia wielu innych wymagań. Po spełnieniu wszystkich warunków można użyć break, który przekaże kontrolę z powrotem do głównej części programu. Również, aby spełnić inne warunki, oczywiście warunkowe instrukcje mogą być dodawane do struktur sterujących: case statement i possible while loop.

Przykład użycia deklaracji case do spełnienia żądania

#! /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
 2
Author: oOpSgEo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-08 09:43:18

Zauważyłem, że nikt nie opublikował odpowiedzi pokazującej Wielowierszowe menu echo dla tak prostego wprowadzania przez użytkownika, więc oto moja propozycja:

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

Ta metoda została opublikowana w nadziei, że ktoś może uznać ją za przydatną i oszczędzającą czas.

 2
Author: Yokai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 07:42:38

Tak / Nie / Anuluj

Funkcja

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

Użycie

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

Potwierdź czystym wejściem użytkownika

Funkcja

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

Użycie

if @confirm 'Confirm?' ; then
  echo "Yes"
else
  echo "No"
fi
 0
Author: Eduardo Cuomo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 18:53:22

W odpowiedzi dla innych:

Nie musisz określać wielkości liter w BASH4, po prostu Użyj',,', aby utworzyć var małymi literami. Również bardzo nie lubię umieszczać kodu wewnątrz bloku odczytu, uzyskać wynik i poradzić sobie z nim poza blokiem odczytu IMO. Dołącz również " q " Dla quit IMO. Na koniec dlaczego wpisz 'yes' wystarczy użyć -N1 i nacisnąć Y.

Przykład: użytkownik może nacisnąć y / n, a także q, aby po prostu zamknąć.

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
Author: Mike Q,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 03:09:41