Warum wird das Menü nicht wiederholt?

7

Ich verwende GNU Bash, Version 4.3.46 auf einem Ubuntu-Computer. Aus irgendeinem Grund funktioniert diese while-Schleife nicht wie erwartet.

Das Menü sollte sich so lange wiederholen, bis der Benutzer beschließt, das Programm zu beenden. Anschließend wird eine Fehlerprüfung durchgeführt, die den Benutzer auffordert, wenn er sicher ist, dass das Programm beendet wird.

Hier ist der Code:

#!/bin/bash

menu_choice=0
quit_program="n"

while [[ $menu_choice -ne 3 && $quit_program != "y" ]]
do

    printf "1. Backup\n"
    printf "2. Display\n"
    printf "3. Exit\n\n"

    printf "Enter choice: \n"
    read menu_choice

    if [ $menu_choice -eq 3 ]
    then
        printf "Are you sure you want to quit? (y/n)\n"
        read quit_program

    fi

done

Ich denke, es muss möglicherweise mit globalen Variablen deklariert werden und ich lese lokal einen neuen Wert ein ...

Mondo192
quelle
Sie sagen, es funktioniert nicht wie erwartet, aber wie ist das tatsächliche Verhalten?
TheWanderer
Hallo @ Zacharee1, das Menü wird wiederholt, wenn der Benutzer eine Ganzzahl 1 oder 2 eingibt, aber unter Option 3 wird keine Schleife ausgeführt, wenn der Benutzer aufgefordert wird, das Menü zu beenden. Das Programm sollte auch dann eine Schleife durchlaufen, wenn sie "n" eingeben, das Programm jedoch beendet wird.
Mondo192
1
Das liegt daran, dass Sie &&für die Bedingungen in der while-Schleife verwenden. Sie möchten, dass es eine Schleife durchführt, solange eines der beiden wahr ist, nicht beide gleichzeitig. Versuchen Sie es ||stattdessen.
TheWanderer
2
Dies sollte auf Stackoverflow sein
PeterM
1
@PeterM Bash ist hier zum Thema.
TheWanderer

Antworten:

7

Das Problem liegt in Ihren while-Schleifenbedingungen. Diese Linie:

while [[ $menu_choice -ne 3 && $quit_program != "y" ]]

sagt "während menu_choice nicht 3 ist und quit_program nicht y ist, mach eine Schleife weiter." Das Problem ist, dass die while-Schleife endet, wenn eine dieser Bedingungen nicht mehr erfüllt ist.

Was Sie wollen, ist Folgendes:

while [[ $menu_choice -ne 3 || $quit_program != "y" ]]

mit ||anstelle von &&. Auf diese Weise wird die while-Schleife so lange fortgesetzt, wie eine der beiden Bedingungen erfüllt ist, anstatt beide.

Der Wanderer
quelle
1
Das Überprüfen der menu_choiceVariablen ist eine unnötige Überprüfung für die while-Schleife. Es wird für die Schleife überhaupt nicht benötigt und verkompliziert den Code umsonst. Siehe meine Antwort.
Dorian
@Dorian du hast das nicht abgelehnt, oder?
TheWanderer
Ich stimme den Antworten anderer Leute nicht zu, es sei denn, sie sind völlig falsch oder weit von der Basis entfernt.
Dorian
7

Dieses einfachere Skript sollte für Sie funktionieren

#!/bin/bash

menu_choice=0
quit_program=false

while [ $quit_program == false ]
do

    printf "1. Backup\n"
    printf "2. Display\n"
    printf "3. Exit\n\n"

    printf "Enter choice: \n"
    read menu_choice

    if [ $menu_choice -eq 3 ]
    then
        printf "Are you sure you want to quit? (y/n) "
        read ask
        if [ $ask == "y" ]
        then
            quit_program=true
        fi

    fi

done

printf "\nDone\n"

Es ist nicht erforderlich, das zu überprüfen menu_choice, damit es aus der while-Schleifenprüfung entfernt werden kann.

In meinem obigen Beispiel habe ich nur einen Booleschen Wert festgelegt, der quit_programin der Schleife überprüft wird. Wenn der Benutzer Option 3 wählt und dann zur Bestätigung "y" sagt, wird der Boolesche Wert auf "true" gesetzt, um die Schleife zu beenden.

Sie können auch noch weiter gehen, ohne einen Booleschen Wert zu überprüfen:

#!/bin/bash

menu_choice=0

while true
do
    printf "1. Backup\n"
    printf "2. Display\n"
    printf "3. Exit\n\n"

    printf "Enter choice: \n"
    read menu_choice

    if [ $menu_choice -eq 3 ]
    then
        printf "Are you sure you want to quit? (y/n) "
        read ask
        if [ $ask == "y" ]; then break; fi
    fi
done

printf "\nDone\n"

Dieses zweite Beispiel führt dasselbe aus, aber die whileSchleife wird nur ausgeführt, ohne den Booleschen Wert von zuvor zu überprüfen. Die Schleife wird breakstattdessen mit dem Befehl unterbrochen .

Dorian
quelle