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.

22voto

Dennis Punkte 51330

Diese Lösung liest ein einzelnes Zeichen und ruft eine Funktion bei einer Ja-Antwort auf.

read -p "Sind Sie sicher? (j/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    etwas_machen      
fi

2 Stimmen

@Jav der echo druckt eine neue Zeile nach Ihrer Antwort aus. Ohne ihn würde das nächste zu druckende Element sofort nach Ihrer Antwort in derselben Zeile erscheinen. Versuchen Sie, das echo zu entfernen, um es selbst zu sehen.

21voto

Thorsten Staerk Punkte 1020

Um eine schöne ncurses-ähnliche Eingabebox zu erhalten, verwenden Sie den Befehl dialog folgendermaßen:

#!/bin/bash
if (dialog --title "Nachricht" --yesno "Möchten Sie etwas Riskantes tun?" 6 25)
# Die Meldungsbox hat eine Größe von 25x6 Zeichen
then 
    echo "Lass uns etwas Riskantes tun"
    # Führe etwas Riskantes aus
else 
    echo "Lass uns langweilig bleiben"
fi

Das Dialogpaket ist standardmäßig mindestens bei SUSE Linux installiert. Sieht so aus: Der Befehl

0 Stimmen

Es gibt auch ein --defaultno Argument, um sicherzustellen, dass die Option "Nein" standardmäßig ausgewählt ist.

21voto

Léa Gris Punkte 14520

Es ist möglich, eine lokalisierte "Ja / Nein Auswahl" in einer POSIX-Shell zu behandeln; indem man die Einträge der LC_MESSAGES Lokalisierungskategorie verwendet, die vorgefertigte RegEx-Muster zum Abgleichen eines Eingangs und lokalisierte Ja-Nein-Strings bereitstellt.

#!/usr/bin/env sh

# LC_MESSAGES-Werte in Variablen übernehmen
# shellcheck disable=SC2046 # Beabsichtigtes IFS-Splitting
IFS='
' set -- $(locale LC_MESSAGES)

yesexpr="$1"
noexpr="$2"
yesstr="$3"
nostr="$4"
messages_codeset="$5" # hier nicht verwendet, aber als Dokumentation beibehalten

# Ja / Nein ?-Prompt in der Lokalisierung anzeigen
echo "$yesstr / $nostr ?"

# Antwort einlesen
read -r yn

# Antwort überprüfen
case "$yn" in
# Abgleich funktioniert nur mit dem Zeichenklassenanteil des Ausdrucks
  ${yesexpr##^}) echo "Antwort $yesstr" ;;
  ${noexpr##^}) echo "Antwort $nostr" ;;
esac

BEARBEITEN: Wie @Urhixidur in seinem Kommentar erwähnt hat:

Leider spezifiziert POSIX nur die ersten beiden (yesexpr und noexpr). Auf Ubuntu 16 sind yesstr und nostr leer.

Siehe: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06

LC_MESSAGES

Die Lokalisierungsstichwörter yesstr und nostr sowie die Langinfo-Elemente YESSTR und NOSTR wurden früher verwendet, um Benutzerantworten auf Ja und Nein abzugleichen. In POSIX.1-2008 wurden die erweiterten regulären Ausdrücke yesexpr, noexpr, YESEXPR und NOEXPR eingeführt, die sie ersetzten. Anwendungen sollten die allgemeinen Lokalisierungs-Messaging-Einrichtungen verwenden, um Aufforderungsnachrichten mit Beispielerwartungen auszugeben.

Alternativ können Sie die Bash-Methoden mit Lokalisierungen verwenden:

#!/usr/bin/env bash

IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES)

printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr"

printf -v prompt $"Bitte beantworten Sie mit Ja (%s) oder Nein (%s): " "$yesexpr" "$noexpr"

declare -- answer=;

until [[ "$answer" =~ $yes_or_no_regex ]]; do
  read -rp "$prompt" answer
done

if [[ -n "${BASH_REMATCH[1]}" ]]; then
  echo $"Sie haben mit Ja geantwortet."
else
  echo $"Nein, war Ihre Antwort."
fi

Die Antwort wird mit den bereitgestellten regulären Ausdrücken der Lokalisierungsumgebung abgeglichen.

Um die verbleibenden Nachrichten zu übersetzen, verwenden Sie bash --dump-po-strings scriptname, um die PO-Strings für die Lokalisierung auszugeben:

#: scriptname:8
msgid "Bitte beantworten Sie mit Ja (%s) oder Nein (%s): "
msgstr ""
#: scriptname:17
msgid "Sie haben mit Ja geantwortet."
msgstr ""
#: scriptname:19
msgid "Nein, war Ihre Antwort."
msgstr ""

0 Stimmen

Ich liebe die Hinzufügung einer sprachagnostischen Option. Gut gemacht.

1 Stimmen

Leider spezifiziert POSIX nur die ersten beiden (yesexpr und noexpr). Auf Ubuntu 16 sind yesstr und nostr leer.

2 Stimmen

Aber Moment mal! Es gibt noch schlechtere Nachrichten! Die Bash "case" Anweisungsausdrücke sind nicht regulär, sondern Dateinamen-Ausdrücke. Daher werden Ubuntu 16's yesexpr und noexpr ("^[yY].*" und "^[nN].*", jeweils) vollkommen versagen, wegen des eingebetteten Punktes. In einem regulären Ausdruck bedeutet ".*" "jedes Nicht-Zeilenende-Zeichen, null oder mehr Mal". Aber in einer "case" Anweisung ist es ein wörtlicher "." gefolgt von einer beliebigen Anzahl von Zeichen.

16voto

user9869932 Punkte 5353

In meinem Fall musste ich aus einem heruntergeladenen Skript lesen, d.h.,

curl -Ss https://beispiel.com/installer.sh | sh

Die Zeile read -r yn ermöglichte es, in diesem Fall Eingaben zu lesen.

printf "Diese Dateien werden hochgeladen. Ist das ok? (y/N) " read -r yn

0 Stimmen

Ein wichtiger Teil davon ist die Eingabevalidierung. Ich denke, dass die Anpassung meines ersten Beispiels, um tty-Eingaben zu akzeptieren, wie Sie es getan haben, genauso gut für Sie funktioniert hätte und auch eine Schleife bei ungültiger Eingabe erzeugt hätte (stellen Sie sich ein paar Zeichen im Puffer vor; Ihre Methode würde den Benutzer dazu zwingen, immer Nein zu wählen).

13voto

Walter A Punkte 17808

Sie können das Standard-ANTWORT auf einem lesen verwenden, in Kleinbuchstaben umwandeln und mit einem Ausdruck mit einer Reihe von Variablen vergleichen.
Das Skript unterstützt auch ja/si/oui

read -rp "Möchten Sie eine Demo? [j/n/a] "

[[ ${REPLY,,} =~ ^(a|abbrechen)$ ]] && { echo "Abbrechen ausgewählt"; exit 1; }

if [[ ${REPLY,,} =~ ^(j|ja|s|si|o|oui)$ ]]; then
   echo "Positiv"
fi

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