1863 Stimmen

Wie fordere ich Eingaben für Ja/Nein/Abbrechen in einem Linux-Shell-Skript ab?

Ich möchte die Eingabe in einem Shell-Skript pausieren und den Benutzer nach Entscheidungen fragen.
Die Standardfrage für die Typen Ja, Nein oder Abbrechen.
Wie kann ich das in einem typischen Bash-Prompt erreichen?

40 Stimmen

Just als Hinweis: Die Konvention für Aufforderungen besagt, dass wenn Sie eine Option [yn] präsentieren, die Großschreibung die Standardeinstellung ist, d.h. [Yn] wird standardmäßig auf "yes" und [yN] auf "no" festgelegt. Siehe ux.stackexchange.com/a/40445/43532

4 Stimmen

Jeder, der von ZSH hierher kommt, siehe diese Antwort für die Verwendung des read Befehls zur Aufforderung

2 Stimmen

Sie können auch meine zugehörige Frage/Antwort auf U&L.SE zur kanonischen Art, in bash zu pausieren, in Betracht ziehen. Die bereitgestellten Ergebnisse können einfach übertragen werden.

695voto

F. Hauri Punkte 57640

Mindestens fünf Antworten auf eine generische Frage.

Je nach

  • posix konform: könnte auf schlechten Systemen mit generischen Shell Umgebungen
  • bash spezifisch: Verwendung der so genannten Bashismen

und wenn Sie wollen

  • einfache ``in line'' Frage/Antwort (generische Lösungen)
  • hübsch formatierte Schnittstellen, wie ncurses oder mehr grafisch mit libgtk oder libqt...
  • Nutzung der leistungsstarken Funktion "Readline History

1. Generische POSIX-Lösungen

Sie könnten die read Befehl, gefolgt von 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 # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist.
    echo Yes
else
    echo No
fi

(Dank an Adam Katz' Kommentar : Ersetzte den obigen Test durch einen, der portabler ist und eine Gabelung vermeidet:)

POSIX, aber ein einziges Schlüsselmerkmal

Wenn Sie aber nicht wollen, dass der Benutzer die Taste Return könnten Sie schreiben:

( Bearbeitet: Als @JonathanLeffler zu Recht vorschlagen, Sparen stty-Konfiguration besser sein könnte, als sie einfach dazu zu zwingen vernünftig .)

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

Nota: Dies wurde getestet unter sh , bash , ksh , Bindestrich y busybox !

Dasselbe, aber ich warte ausdrücklich auf y o 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

Verwendung spezieller Tools

Es gibt viele Tools, die mit Hilfe von libncurses , libgtk , libqt oder andere grafische Bibliotheken. Zum Beispiel, mit whiptail :

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

Je nach System müssen Sie möglicherweise Folgendes ersetzen whiptail mit einem anderen, ähnlichen Werkzeug:

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

donde 20 ist die Höhe des Dialogfelds in Anzahl der Zeilen und 60 ist die Breite des Dialogfelds. Diese Werkzeuge haben alle nahezu gleich Syntax.

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

2. Bash-spezifische Lösungen

Grundlegend im Einklang 方法

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

Ich bevorzuge die Verwendung von case so dass ich sogar testen konnte, ob yes | ja | si | oui falls erforderlich...

im Einklang con einzelne Taste Funktion

Unter der Bash können wir die Länge der beabsichtigten Eingabe für den Befehl read Befehl:

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

Unter bash, read Befehl akzeptiert eine Timeout Parameter, der nützlich sein könnte.

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

3. Einige Tricks für dedizierte Tools

Anspruchsvollere Dialogfelder, die über einfache yes - no Zwecke:

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

Fortschrittsbalken:

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
) 

Kleine 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

Mehr Beispiele? Schauen Sie sich an Whiptail zur Auswahl eines USB-Geräts verwenden y USB-Wechselspeicher-Auswahl: USBKeyChooser

5. Verwendung der Readline-Historie

Beispiel:

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

Dadurch wird eine Datei erstellt .myscript.history in Ihrem $HOME Verzeichnis, dann können Sie die history-Befehle von readline verwenden, wie Up , Down , Ctrl + r und andere.

6 Stimmen

Beachten Sie, dass stty die Option -g für die Verwendung bereitstellt: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty". Dies stellt die Einstellungen genau so wieder her, wie sie vorgefunden wurden, was möglicherweise nicht mit stty -sane übereinstimmt.

7 Stimmen

read answer wird Schrägstriche vor Leerzeichen und Zeilenumbrüchen interpretieren und ansonsten entfernen, was selten beabsichtigt ist. Verwenden Sie stattdessen read -r answer gemäß SC2162.

0 Stimmen

@vlfig Einverstanden: Die Erwartung von Backslashes aus Benutzereingaben in einem Ja/Nein/Abbrechen-Dialog ist selten beabsichtigt... Ich denke, dass dies der Hauptgrund ist, warum ich die Option -r nicht verwendet habe.

359voto

Pistos Punkte 22071
echo "Bitte geben Sie eine Eingabe ein: "
read input_variable
echo "Sie haben eingegeben: $input_variable"

35 Stimmen

Ich widerspreche, weil es nur einen Teil der Funktionalität des 'Ja, Nein, Abbrechen'-Dialogs in DOS implementiert. Der Teil, den es nicht umsetzt, ist die Eingabeüberprüfung... Schleifen, bis eine gültige Antwort erhalten wird.

4 Stimmen

Wie fordere ich Eingaben in einem Linux-Shell-Skript an?

8 Stimmen

Aber die ursprüngliche Fragebeschreibung bleibt unverändert und erfordert immer eine Antwort auf eine Ja/Nein/Abbrechen-Aufforderung. Der Titel wurde aktualisiert, um klarer zu sein als mein Originaltitel, aber die Fragebeschreibung war immer klar (meiner Meinung nach).

178voto

yPhil Punkte 7419

Sie können das integrierte read Befehl verwenden ; Verwenden Sie die -p Option, um den Benutzer mit einer Frage aufzufordern.

Seit BASH4 können Sie jetzt -i verwenden, um eine Antwort vorzuschlagen:

read -e -p "Geben Sie den Pfad zur Datei an: " -i "/usr/local/etc/" DATEIPFAD
echo $DATEIPFAD

(Aber denken Sie daran, die "readline" Option -e zu verwenden, um die Zeilenbearbeitung mit den Pfeiltasten zu ermöglichen)

Wenn Sie eine "ja / nein" Logik möchten, können Sie etwas wie folgt tun:

read -e -p "
Inhalt Ihres Home-Verzeichnisses auflisten ? [J/n] " JA

[[ $JA == "j" || $JA == "J" || $JA == "" ]] && ls -la ~/

6 Stimmen

Es sei darauf hingewiesen, dass FILEPATH der von Ihnen gewählte Variablenname ist und mit der Antwort auf die Befehlsaufforderung eingestellt wird. Wenn Sie dann beispielsweise vlc "$FILEPATH" ausführen würden, würde vlc diese Datei öffnen.

0 Stimmen

Was ist der Vorteil von -e im zweiten Beispiel (einfach ja/nein)?

0 Stimmen

Gibt es einen Grund, -e -p anstelle von -ep zu verwenden?

128voto

Steven Huwig Punkte 18929

Bash hat select für diesen Zweck. So würden Sie es in einem Skript verwenden:

select result in Ja Nein Abbrechen
do
    echo $result
done

So würde es aussehen, wenn Sie es verwenden würden:

$ bash beispielskript.sh
1) Ja
2) Nein
3) Abbrechen
#? 1
Ja
#? 2
Nein
#? 3
Abbrechen
#?

24 Stimmen

+1 Genial einfache Lösung. Nur eine Sache: Das wird prompt und prompt und prompt ... bis du exit hinzufügst :)

7 Stimmen

(kaiser: Um auszusteigen, geben Sie einfach das EOT ein: Strg-D. Aber natürlich wird echter Code, der es verwendet, eine Unterbrechung oder einen Ausstieg im Körper benötigen.)

19 Stimmen

Dies wird es Ihnen nicht erlauben, y oder n einzugeben. Sie wählen, indem Sie 1 2 oder 3 eingeben.

66voto

serg Punkte 629
lesen -p "Geht es dir gut? (j/n) " RESP
if [ "$RESP" = "j" ]; then
  echo "Gut zu hören"
else
  echo "Du brauchst mehr Bash-Programmierung"
fi

0 Stimmen

Dies ist der lesbarste. +1

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X