Wie wird Bash den folgenden Code auswerten?

Wie wird Bash den folgenden Code auswerten?

Diese Frage besteht aus zwei Teilen:

(a) Verstehen, was der ausgeschnittene Code bewirkt

(b) Den Unterschied verstehen zwischenBeendigungsstatusUndRückgabestatusim Kontext von bash.

Hier ist der Codeausschnitt, den ich zu verstehen versuche:

if var=-2 && (( var+=2 ))
then
    echo "True"
else
    echo "False"
fi

Beim Ausführen wird Folgendes erzeugt False: Ich kann nicht verstehen, warum das passiert.

Wenn ich das richtig verstehe, passiert möglicherweise Folgendes mit der ifBedingung:

(a) var=-2erzeugt den Exit-Status 0, da die Zuweisung erfolgreich war

(b) (( var+=2 ))addiert 2 zum Wert von varund der Ausdruck ergibt Null. Der Beendigungsstatus für diesen Term ist also 1

(c) 0 && 1 erzeugt einen Exist-Status von 0, der dann von der ifKonstruktion verwendet wird

Das ifKonstrukt soll einfach den Exit-Status prüfen und wenn dieser Null ist, nimmt es denDannPfad. In Schritt (c) oben ist es Null, aber das Skript nimmt trotzdem denandersPfad. Ist das die richtige Art, das zu verstehen?

Außerdem sehe ich immer wieder verschiedene bashTexte verwendenBeendigungsstatusUndRückgabestatusaustauschbar.

Ich bezweifle, var=-2dass die Zuweisung irgendeinen Beendigungsstatus haben würde, da es sich nicht um ein Programm handelt. Aber jede Klarstellung des Unterschieds zwischen beiden wäre großartig.

Antwort1

Das ist:

if
  first list of commands
then
  second list of commands
else
  third list of commands
fi

Das heißt, die zweite Befehlsliste wird ausgeführt, wenn die erste Befehlsliste mit einemWAHR/Erfolg(Null) Exit-Status, d. h. wenn der letzte Ausführungsbefehl dort mit einem Exit-Status von Null zurückkehrt.

In:

var=-2 && ((var += 2))

Es wird nur cmd1 && cmd2ausgeführt cmd2, wenn cmd1es erfolgreich ist.

var=-2

Ist normalerweise erfolgreich, solange der $varSchreibschutz nicht aktiviert wurde, sodass der ((var += 2))Befehl ausgeführt wird:

((arithmetic expression))

Kehrt zurückErfolg/WAHRsolange der Ausdruck korrekt ausgewertet wird (kein Syntaxfehler) und das Ergebnis des Ausdrucks ungleich Null ist.

  • ((123)), ((1 + 1)), ((1 == 1))return true
  • ((0)), ((-2 + 2)), ((2 == -2))falsch zurückgeben.
  • ((4294967296 * 4294967296))gibt in den meisten Shells false zurück, da 64-Bit-Integer-Wrapping

var += 2als arithmetischer Ausdruck, führt die Zuweisung aus und ergibt den zugewiesenen Wert, hier 0, daher dieFALSCHBeendigungsstatus.

Sie können den Wert anzeigen, auf dem der Beendigungsstatus basiert, indem Sie die $((...))Syntax der arithmetischen Erweiterung verwenden:

$ echo "$((1 + 1)) $((2 == 2)) $((2 == -2)) $((var = -2)) $((var += 2))"
2 1 0 -2 0

Oder durch Zuweisen zu einer Variablen:

$ var=-2; ((result = (var += 2)))
$ echo "$? $result $var"
1 0 0

$?enthält den Beendigungsstatus des vorherigen Befehls. Bei if/ then/ else/ fibedeutet 0 wahr, alles andere bedeutet falsch.

Die Verwirrung rührt hier daher, dass es bei arithmetischen Ausdrücken umgekehrt ist: 0bedeutet falsch und alles andere bedeutet wahr (z. B. 2 == 2ist , 1während 2 < 1ist 0).

Um sich keine Sorgen über den Unterschied zu machen, vergessen Sie einfach $?und seine möglichen Werte. Denken Sie einfach an BoolescheWAHR/FALSCH,Erfolg/Versagen.

 grep -q foo file

Gibt „true“ zurück, wenn fooin gefunden wird file.

 [ "$a" = "$b" ]

Gibt „true“ zurück, wenn $adasselbe wie enthält $b.

 ((6 * 3 - 12))
 ((4 == 1))

Gibt „true“ zurück, wenn das Ergebnis des arithmetischen Ausdrucks eine von Null verschiedene Zahl ist.

Es spielt keine Rolle, ob dieseWAHR/FALSCHwerden durch 0 oder 1 als Beendigungsstatus dieser grep/ [Befehle oder ((...))Konstrukte ausgedrückt.

Antwort2

(c) 0 && 1 erzeugt einen Exist-Status von 0, der dann von der ifKonstruktion verwendet wird

Da liegt der Fehler. 0 && 1 ergibt 1. Denken Sie daran, das ist nicht C oder Java. In der Shell erhalten Sie 0 && 1 von true && false.

$ true; echo $?
0
$ false; echo $?
1
$ true && false; echo $?
1

Außerdem sehe ich immer wieder, dass in verschiedenen Bash-Texten die Begriffe „Exit-Status“ und „Return-Status“ synonym verwendet werden.

Sie sind austauschbar. Was Sie im Hinterkopf behalten sollten, ist, dass 0Erfolg anzeigt und Nicht- 0Misserfolg anzeigt. Es ist das Gegenteil der meisten Programmiersprachen, wo 0falsch und 1wahr ist.

Antwort3

Alles funktioniert wie erwartet.

if var=-2 && (( var+=2 ))
then
    echo "True"
else
    echo "False"
fi

Codeerklärung: -

if var=-2 && (( var+=2 ))

var=-2 => true Der Wert ist ungleich Null und wird daher als wahr ausgewertet.

var+=2 => false Der Wert ist Null und wird daher als „false“ ausgewertet.

das ist wie

if true && false

Gemäß logischer Berechnungwahr && falsch => falsch

In diesem Fall ist hier unser endgültiger Code

if (false)
then
    echo "True"
else
    echo "False"
fi

verwandte Informationen