Switch Case funktioniert in Shell nicht

Switch Case funktioniert in Shell nicht

Ich möchte gdialogBenutzereingaben entgegennehmen und sie in der Shell an Switch Case weitergeben. Unten ist mein Code:

#!/bin/sh


which gdialog 2> /dev/null && DIALOG=gdialog || DIALOG=dialog

end () {
    # rm -f $FILE1 $FILE2 $ERROR
    echo "User pressed cancel!"
exit
}

while true
do
    choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
    "Date" "Get today's date" \
    "Time" "Get today's time")|| end

    # echo $choice

    case "$choice" in
            "Date")

            MSG="Date is requested"
            echo $MSG
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
            "Time")
            MSG="Time is requested!"
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
    esac
done

Das Problem besteht darin, dass der Switch-Case ausgeführt wird und der Kontrollfluss den ersten oder zweiten Case erreicht, die Zeile nach der Variablendeklaration jedoch MSGnicht ausgeführt wird. Ich möchte den Benutzer mit „yes“/„no“ fragen, ob er fortfahren möchte gdialog. Was mache ich hier falsch?

Antwort1

Die Befehlsersetzung wird durch die Standardausgabe des Befehls ersetzt. Dialog verwendet stdout, um seine Benutzeroberfläche anzuzeigen, gdialog verwendet es meines Wissens überhaupt nicht. Beide verwenden stderr, um das Ergebnis zurückzugeben.

Eine Möglichkeit, dafür zu sorgen, dass Ihr Skript wie erwartet funktioniert, besteht darin, bei der Befehlsersetzung stdout durch stderr zu ersetzen:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3)|| end

Antwort2

dialogschreibt sein Ergebnis in den Standardfehler, sofern Sie nicht eine Umleitung durchführen oder die --stdoutOption verwenden (da es wie jede Curses-Anwendung seine Anzeige standardmäßig in die Standardausgabe schreibt und den Standardfehler meldet). Bei würden Sie das nicht bemerken gdialog, da es seine Anzeige in ein anderes Fenster schreibt.

Aus diesem Grund gdialogwürde ich schreibenNichtszur Standardausgabe und $choicewäre leer. Das Skript führt die Case-Anweisung aus, aber stimmt mit keinem der Fälle überein. In der Regel sollten Case-Anweisungen einen Standardwert haben, z. B.*)damit Sie eine Nachricht hinterlassen könnenDortund sehen Sie, was los ist.

Nicht Teil der Frage, aberWieum das Problem zu umgehen, scheint zu erwarten. Das Skript verweist auf gdialog, was wahrscheinlich ein Skript ist, das zenity(dasOriginalgdialogIstlange vorbei). Keines der beiden Programme bietet diese --stdoutOption an, obwohl sie wahrscheinlich schon vor beiden Programmen existierte (sieheChangelog-Eintrag von 2000). Sie können das in der Shell umgehen, indem Sie die Dateideskriptoren gegen die Standardausgabe und den Fehler austauschen. Das ist seit Ende 2000 auch in den Beispielskripten von Dialog enthalten, und zwar auf Grundlage eines Vorschlags von Carey Evans (Entwickler von tn5250):

    Es ist möglich, die Ausgabe des Dialogs zu erfassen, ohne
    temporäre Dateien überhaupt, wie ich es im „xt5250“-Skript von tn5250 getan habe:

        Ausführung 3>&1
        XT5250_HOST="`$DIALOG --backtitle "xt5250" --title "Mit Host verbinden" \
          --inputbox "Geben Sie den Namen oder die IP-Adresse des Hosts ein, mit dem eine Verbindung hergestellt werden soll:" \
          7 60 2>&1 1>&3`"
        ret=$?
        ausführen 3>&-

    Vielleicht könnten Sie in Erwägung ziehen, so etwas zu verwenden, anstatt
    temporäre Dateien. Der Trick mit zusätzlichen FDs wird etwas schwierig
    aber lesen.

    > (es sind jedoch Beispiele – wie viel Arbeit muss ich investieren, um sie sicher zu machen?)

    Die Leute werden sie ausschneiden und einfügen.

Wenn man dem zustimmt, hilft es, Skripte anzuhalten und zu erklären. Die Bash-Dokumentation hilft hier weiter, mitVerschieben von DateideskriptorenDieses Skript

(sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null

kann von rechts nach links gelesen werden als (a) Verschieben des Dateideskriptors 1 (stdout) bis 3, 2 (stderr) auf 1 und dann auf 3 (ursprünglichstdout) zu 2.

Sie könnten Ihr Skript also verbessern, indem Sie die gleiche Reihe von Änderungen in die Dateideskriptoren einfügen:

3>&2 2>&1 1>&3

in der Zuordnung zu choice:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3 )|| end

Weiterführende Literatur:

verwandte Informationen