Bessere Möglichkeit, Variationen von "Ja" von einer Shell-Eingabeaufforderung aus zu akzeptieren


27

Beim Usability-Test eines von mir geschriebenen Shell-Skripts stellte sich heraus, dass die Leute unterschiedliche Erwartungen an die Beantwortung einer Frage hatten, die mit "Ja" als Antwort erwartet wurde. Siehe Variationen im folgenden Codebeispiel.

Sicherlich muss es einen besseren Weg geben als den, den ich mir ausgedacht habe? Was ist Ihre lesbare und kürzere Form ?

read -p 'Answer this question with yes: ' answer
if [ "$answer" = 'Y'
  -o "$answer" = 'YES'
  -o "$answer" = 'Yes'
  -o "$answer" = 'y'
  -o "$answer" = 'yes'
  -o some-alternate-condition ]; then

  echo 'Surely this can be written better?'
fi

2
Zum Abschluss gewählt. Während ich an der Frage interessiert bin, handelt es sich wahrscheinlich eher um eine Programmierfrage, sollte also auf SO stehen.
Phunehehe

Eine Programmierantwort könnte so etwas wie Bash sein: Überprüfen Sie, ob ein Array-Element vorhanden ist
phunehehe

3
@phunehehe: Ich bin nicht einverstanden damit, zu SO zu wechseln, nicht nur, weil wir die Shell-Programmierung akzeptiert haben, sondern auch, weil es nicht nur darum geht, wie es geht, sondern auch darum, was die Spezifikation sein soll.
Gilles 'SO- hör auf böse zu sein'

4
Ich habe einmal ein ähnliches Drehbuch geschrieben. Dann wurde das Programm ins Französische und Vereinfachte Chinesisch übersetzt. Ich überflog die französische Version und sah, dass meine Eingabeaufforderung in "Enter oui or non" übersetzt wurde, aber natürlich wollte der Code immer noch "Y *" oder "N *"
Ben Jackson

Antworten:


15

Die Verwendung von a caseist etwas äquivalent, aber nicht perfekt, da Aussagen wie YEakzeptiert werden.

read -p 'Answer this question with yes: ' answer
case "${answer}" in
    [yY]|[yY][eE][sS])
        echo 'Surely this can be written better?' ;;
esac

3
Ich würde sagen, die Absicht des Benutzers ist ziemlich klar aus "Sie".
Aeyoun

48

Der UNIX-Standard bietet hierfür Beispielcode mit dem localeDienstprogramm :

if printf "%s\n" "$response" | grep -Eq "$(locale yesexpr)"
then
    affirmative processing goes here
else
    non-affirmative processing goes here
fi

Der Wert für 'yesexpr' in der Ländereinstellung POSIX(und in englischen Ländereinstellungen auf realen Systemen) ist "^[yY]". Es ist als erweiterter regulärer Ausdruck zu interpretieren. Siehe auch noexpr.


1
Nett. Aber ich scheine ein Idiot zu sein. Wo finde ich eine Liste der Argumente, localeüber die ich Bescheid weiß? Die Manpage auf meiner Mac OS 10.5-Box scheint sie nicht zu haben.
dmckee

Nett. Könnten Sie bitte auf die Quelle zurück verlinken?
Aeyoun

3
@dmckee können Sie tun locale -k LC_MESSAGES(und für die anderen LC_was auch immer), oder sehen Sie hier für diejenigen, die durch den Standard definiert sind. @Daniel, aus welcher anderen Quelle als der Seite mit dem Gebietsschemadienstprogramm, die ich verlinkt habe?
Random832

1
Gute Antwort, sollte auf jeden Fall die akzeptierte sein.
Juli

6

Bleiben Sie in der Bash (oder einer anderen Shell, wenn Sie die Eingabeaufforderung unabhängig anzeigen):

case $answer in
  [Yy]*) echo Ok;;
  *) echo "Can't you read? I said to say yes.";;
esac

Dies akzeptiert Antworten wie ynals ja,  y(mit einem anfänglichen Raum) als nein, und wlkjzuhfodwie keine, das ein optimalen möglicherweise nicht sein , ist aber im Einklang mit dem typisch Shell Prompts: das ist , wie rm -i, find -okund andere tun es.

Dies vermeidet das ganze Problem der Internationalisierung: In anderen Sprachen müssten Sie die erwarteten Antworten übersetzen. Dann gibt es keine Standard-Shell-Methode. Sie können zum Dialogfeld wechseln. In diesem Fall muss das Skript installiert werden (es ist in vielen Distributionen verfügbar, wird jedoch nicht immer standardmäßig installiert).

if dialog --yesno "Choose yes" 0 0; then 

3

Normalerweise benutze ich eine einfache Funktion:

Confirm() { read -sn 1 -p "$* [Y/N]? "; [[ ${REPLY:0:1} = [Yy] ]]; }

Die Funktion kehrt nur zurück, 0wenn Yoder yeingegeben wird und 1wenn etwas anderes eingegeben wird. Es kann verwendet werden mit if...fi:

if Confirm "Type y or n"; then
echo "You typed y"
else
echo "You typed n"
fi

Oder einfach so:

Confirm "Type y" && echo "You typed y"

Nehmen Sie das ab -s, um einen visuellen Verlauf dessen zu erhalten, was getippt wurde.
Tom Hale

0

Nur @faif ans geändert

YesOrNo() {
        while :
        do
                read -p 'Do you want to Continue (yes/no?): ' answer
                case "${answer}" in
                    [yY]|[yY][eE][sS]) exit 0 ;;
                        [nN]|[nN][oO]) exit 1 ;;
                esac
        done
}


if $( YesOrNo ); then
        echo "Ans is yes.. Do something....."
else
        echo "Ans is No... skip.."
fi

Prüfung

root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):  # if Blank Enter then ask again
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): no
Ans is No... skip..
root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): ye
Do you want to Continue (yes/no?): yes
Ans is yes.. Do something.....
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.