Tracks
/
Bash
Bash
/
Lehrplan
/
Bedingte Anweisungen
Be

Bedingte Anweisungen in Bash

{one: "1 Übung", other: "%{count} Übungen"}

Über Bedingte Anweisungen

Was in Bash als wahr gilt

Bash kennt das Konzept boolescher Werte nicht. Es gibt Strings und Zahlen sowie Arrays aus Strings oder Zahlen. Wie gehen bedingte Befehle also mit wahr und falsch um?

Exit-Status

Befehle liefern einen Exit-Status, wenn sie enden. Ein Exit-Status ist eine Ganzzahl zwischen 0 und 255 (einschließlich). Bash betrachtet einen Exit-Status von null als Erfolg. Jeder andere Exit-Status steht für einen Fehlschlag.

Das gilt für alle Befehle, auch für die in Bash eingebauten Befehle, Schlüsselwörter und Funktionen.

Der „if“-Befehl

Die grundlegende Syntax des if-Befehls ist

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

Sie beginnt mit if, die Bedingungsbefehle werden durch then von den „Erfolgs“-Befehlen getrennt, und sie wird mit fi beendet. Die else-Klausel ist optional.

CONDITIONAL_COMMANDS kann ein einzelner Befehl sein oder eine Befehlsliste.

Die CONDITIONAL_COMMANDS werden ausgeführt, und

  • ist der Exit-Status null (Erfolg), werden die TRUE_COMMANDS ausgeführt.
  • ist der Exit-Status ungleich null (Fehlschlag), werden die FALSE_COMMANDS ausgeführt, sofern sie vorhanden sind.

Kaskadierende Verzweigungen lassen sich mit elif angeben.

if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi

Vor den Wörtern then, elif, else und fi muss ein Semikolon oder ein Zeilenumbruch stehen.

Zur Betonung: Es ist der Exit-Status der Bedingungsbefehle, der den Ablauf steuert. Ein Beispiel: grep gibt 0 zurück, wenn eine Übereinstimmung gefunden wird, und 1, wenn keine gefunden wird. Die Option -q unterdrückt die Ausgabe und erzeugt nur den Exit-Status.

if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi

Die Befehle „[“ und „test“

Um die CONDITIONAL_COMMANDS herum gibt es keine besondere Syntax. Vielleicht kennst du if-Anweisungen, die so aussehen:

if [ "$password" = "secure" ]; then
    echo "Welcome!"
fi

[ ist keine besondere Syntax. Es ist ein Befehl, der den bedingten Ausdruck auswertet und mit einem Erfolgs- oder Fehlschlagstatus endet. Wie bei allen Befehlen ist zwischen ihm und seinen Argumenten Leerraum erforderlich.

[ ist tatsächlich ein Synonym für den Befehl test. Sie sind genau gleich, nur dass das letzte Argument von [ ] sein muss.

Bedingte Ausdrücke

Innerhalb von [ und ] schreibst du einen bedingten Ausdruck. Einige typische bedingte Ausdrücke sind:

[ -f "$filename" ]             # file operations
[ "$string1" = "$string2" ]    # string comparisons
[ "$num1" -eq "$num2" ]        # arithmetic comparisons

Es gibt noch viele weitere Operationen; sie sind im Abschnitt Bedingte Ausdrücke in Bash des Handbuchs aufgeführt.

Note

In den Beispielen oben fällt auf, dass alle Variablen in Anführungszeichen stehen. Die Befehle test und [ sind einfache Befehle, bei denen die Argumente wie bei jedem anderen Befehl der Wortaufteilung und der Dateinamen-Erweiterung unterliegen.

Das ist wichtig zu erwähnen, weil bedingte Ausdrücke unterschiedlich ausgewertet werden, je nachdem, wie viele Argumente du angibst:

  • 0 Argumente: Der Exit-Status ist ungleich null (Fehlschlag).
  • 1 Argument: Der Exit-Status ist null (Erfolg), wenn das Argument nicht leer ist, und ungleich null, wenn es leer ist.
  • 2 Argumente: Das erste Argument muss ein unärer Operator sein (wie in [ -z "$name" ]) oder ein ! (das den Status des Tests mit einem Argument negiert).
  • und mehr.

Du kannst unerwartete Ergebnisse bekommen, wenn du die Anführungszeichen vergisst:

str=""

# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi

# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi

Das Schlüsselwort „[[“

Das bedingte Konstrukt [[...]] ist kein Befehl, sondern ein Schlüsselwort. Das bedeutet: Obwohl es wie jeder andere Befehl behandelt wird, gelten für es besondere Regeln beim Parsen. Das Besondere an [[ ist, dass die darin expandierten Variablen nicht der Wortaufteilung oder Dateinamen-Erweiterung unterliegen. Das heißt, dieser Befehl verhält sich wie erwartet, selbst ohne Anführungszeichen.

if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi

[[ unterstützt alle bedingten Ausdrücke, die test und [ verarbeiten können. Darüber hinaus bietet [[

  • den Operator =~ für den Abgleich mit regulären Ausdrücken,
  • == und != als Operator für den Abgleich mit Glob-Mustern,
  • && und || als logische Operatoren (besondere Parsing-Regel),
  • < und > als „nackte“ String-Vergleichsoperatoren (besondere Parsing-Regel: Da es sich um Umleitungssymbole handelt, müssen sie in [ maskiert werden).

Es gilt weithin als Konsens, dass diese besonderen Funktionen so viel bringen, dass [[ ausschließlich verwendet werden sollte. (Zum Beispiel der Google Shell Style Guide.)

Der „case“-Befehl

case ist ein weiterer Befehl zur Ablaufsteuerung. Er ähnelt einer „switch“-Anweisung in anderen Sprachen.

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

WORD wird mit jedem PATTERN abgeglichen. Wenn eines passt, werden die COMMANDS ausgeführt.

read -p "Guess the secret word: " word
case "$word" in
    secret) echo "Yes, you guessed it!" ;;
    ??????) echo "That's the right number of letters." ;;
    s*)     echo "You guessed the first letter." ;;
    *)      echo "Not even close! Try again." ;;
esac

Jede COMMANDS-Klausel muss mit zwei Semikolons enden, ;;.

Note
  1. Es gibt Alternativen, bei denen die Ausführung in die nachfolgenden Befehle übergehen kann und der Musterabgleich fortgesetzt wird. Details findest du in dem Handbuch.
  2. Erinnere dich, dass wir Muster im Abschnitt Dateinamen-Erweiterung des Quoting-Konzepts besprochen haben.
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab