GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie fordere ich die Eingabe Ja/Nein/Abbrechen in einem Linux-Shell-Skript auf?

Mindestens fünf Antworten auf eine allgemeine Frage.

Abhängig von

  • posix-kompatibel:könnte auf schlechten Systemen mit generischen Shell-Umgebungen funktionieren
  • Bash-spezifisch:Verwendung sogenannter Bashismen

und wenn Sie möchten

  • einfache ``inline'' Frage/Antwort (allgemeine Lösungen)
  • hübsch formatierte Schnittstellen, wie ncurses oder grafischere mit libgtk oder libqt...
  • verwenden Sie die leistungsstarke Readline-Verlaufsfunktion

1. Generische POSIX-Lösungen

Sie könnten den read verwenden Befehl, gefolgt von if ... then ... else :

printf '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 des Kommentars von Adam Katz:Ersetzte den obigen Test durch einen, der tragbarer ist und eine Gabelung vermeidet:)

POSIX, aber einzelne Schlüsselfunktion

Aber wenn Sie nicht möchten, dass der Benutzer Return drücken muss , könnten Sie schreiben:

(Bearbeitet: Wie @JonathanLeffler zu Recht vorschlägt, Sparen Die Konfiguration von stty könnte besser sein, als sie einfach zu gesunden zu zwingen .)

printf '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

Hinweis: Dies wurde unter sh, bash, ksh, dash und busybox getestet!

Dasselbe, aber explizites Warten auf y oder n :

#/bin/sh
printf '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

Verwenden spezieller Tools

Es gibt viele Tools, die mit libncurses erstellt wurden , libgtk , libqt oder andere grafische Bibliotheken. Verwenden Sie zum Beispiel whiptail :

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

Abhängig von Ihrem System müssen Sie möglicherweise whiptail ersetzen mit einem anderen ähnlichen Tool:

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

wobei 20 ist die Höhe des Dialogfensters in Zeilenzahl und 60 ist die Breite des Dialogfelds. Diese Tools haben alle fast dasselbe 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

Einfach inline Methode

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

Ich bevorzuge case so konnte ich sogar auf yes | ja | si | oui testen bei Bedarf...

an der Reihe mit Einzelschlüssel Funktion

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

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

Unter Bash read Befehl akzeptiert eine Zeitüberschreitung 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 als 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 Proben? Sehen Sie sich Whiptail zur Auswahl von USB-Geräten und USB-Wechselspeichern verwenden an:USBKeyChooser

5. Verwenden des Verlaufs von readline

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 .myscript.history erstellt in Ihrem $HOME Verzeichnis, dann könnten Sie die History-Befehle von readline verwenden, wie Up , Nach unten , Strg +r und andere.


Die einfachste und am weitesten verbreitete Methode, um Benutzereingaben an einem Shell-Prompt zu erhalten, ist read Befehl. Der beste Weg, um seine Verwendung zu veranschaulichen, ist eine einfache Demonstration:

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

Eine andere Methode, auf die Steven Huwig hingewiesen hat, ist Bashs select Befehl. Hier ist dasselbe Beispiel mit 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

Mit select Sie müssen die Eingabe nicht bereinigen – sie zeigt die verfügbaren Optionen an, und Sie geben eine Zahl ein, die Ihrer Auswahl entspricht. Es wird auch automatisch eine Schleife durchlaufen, sodass kein while true erforderlich ist Schleife, um es erneut zu versuchen, wenn sie ungültige Eingaben machen.

Außerdem demonstrierte Léa Gris in ihrer Antwort einen Weg, die Anfragesprache agnostisch zu machen. Die Anpassung meines ersten Beispiels, um mehrere Sprachen besser bedienen zu können, könnte folgendermaßen aussehen:

set -- $(locale LC_MESSAGES)
yesexpr="$1"; noexpr="$2"; yesword="$3"; noword="$4"

while true; do
    read -p "Install (${yesword} / ${noword})? " yn
    if [[ "$yn" =~ $yesexpr ]]; then make install; exit; fi
    if [[ "$yn" =~ $noexpr ]]; then exit; fi
    echo "Answer ${yesword} / ${noword}."
done

Offensichtlich bleiben hier andere Kommunikationsstrings unübersetzt (Installieren, Antworten), die in einer vollständigeren Übersetzung behandelt werden müssten, aber sogar eine Teilübersetzung wäre in vielen Fällen hilfreich.

Sehen Sie sich abschließend die ausgezeichnete Antwort von F. Hauri an.


echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"

Linux
  1. Skript erneut ausführen lassen, wenn Eingabe ja ist?

  2. Formatieren Sie Datum und Uhrzeit für Linux-Shell-Skript oder -Variable

  3. Ausblenden von Benutzereingaben auf dem Terminal im Linux-Skript

  4. So suchen Sie nach Dateien mit Regex im Linux-Shell-Skript

  5. Wie skripte ich eine Ja-Antwort für die Installation von Programmen?

So führen Sie einen Linux-Shell-Befehl / ein Skript im Hintergrund aus

Shell-Scripting für Anfänger – So schreiben Sie Bash-Scripts unter Linux

So speichern Sie einen Linux-Befehl als Variable im Shell-Skript

So führen Sie Shell-Skript als SystemD-Dienst in Linux aus

Linux – Wie führen Sie ein Skript aus, das durch eine Joystick-Eingabe ausgelöst wird?

Wie installiere/erstelle ich eine benutzerdefinierte Eingabeaufforderung für die Fischschale?