Siehe die folgenden Beispiele und ihre Ausgaben in POSIX-Shells:
false;echo $?
oderfalse || echo 1
:1
false;foo="bar";echo $?
oderfoo="bar" && echo 0
:0
foo=$(false);echo $?
oderfoo=$(false) || echo 1
:1
foo=$(true);echo $?
oderfoo=$(true) && echo 0
:0
Wie in der am höchsten bewerteten Antwort unter /programming/6834487/what-is-the-variable-in-shell-scripting erwähnt :
$?
wird verwendet, um den Rückgabewert des zuletzt ausgeführten Befehls zu ermitteln.
Dies ist in diesem Fall wahrscheinlich etwas irreführend. Lassen Sie uns also die POSIX-Definition erhalten, die auch in einem Beitrag aus diesem Thread zitiert wird:
? Wird auf den dezimalen Exit-Status der letzten Pipeline erweitert (siehe Pipelines).
Es sieht also so aus, als ob eine Zuweisung selbst als Befehl (oder vielmehr als Pipeline-Teil) mit einem Exit-Wert von Null zählt, der jedoch vor der rechten Seite der Zuweisung gilt (z. B. die Befehlsersetzungsaufrufe in meinen Beispielen hier).
Ich sehe, wie dieses Verhalten aus praktischer Sicht sinnvoll ist, aber es scheint mir etwas ungewöhnlich, dass die Aufgabe selbst in dieser Reihenfolge zählt. Um klarer zu machen, warum es mir fremd ist, nehmen wir an, dass die Aufgabe eine Funktion war:
ASSIGNMENT( VARIABLE, VALUE )
dann foo="bar"
wäre es
ASSIGNMENT( "foo", "bar" )
und foo=$(false)
wäre so etwas wie
ASSIGNMENT( "foo", EXECUTE( "false" ) )
was bedeuten würde , dass die EXECUTE
Läufe zuerst und erst danach ASSIGNMENT
ausgeführt wird , aber es ist immer noch der EXECUTE
Status, der hier ankommt.
Bin ich in meiner Einschätzung richtig oder missverstehe / vermisse ich etwas? Sind das die richtigen Gründe, warum ich dieses Verhalten als "seltsam" betrachte?
false;foo="bar";echo $?
immer 0 zurückgegeben, wenn der letzte echte Befehl ausgeführt wurdefalse
?" Grundsätzlich verhalten sich Zuweisungen besonders, wenn es um Exit-Codes geht. Ihr Exit-Code ist immer 0, außer wenn dies nicht auf etwas zurückzuführen ist, das als Teil der rechten Seite der Zuweisung ausgeführt wurde.Antworten:
Der Exit-Status für Zuweisungen ist seltsam . Die offensichtlichste Möglichkeit, dass eine Zuweisung fehlschlägt, besteht darin, dass die Zielvariable markiert ist
readonly
.Beachten Sie, dass weder der wahre noch der falsche Pfad der if-Anweisung verwendet wurden. Die fehlgeschlagene Zuweisung hat die Ausführung der gesamten Anweisung gestoppt. bash im POSIX-Modus und ksh93 und zsh brechen alle ein Skript ab, wenn eine Zuweisung fehlschlägt.
Um den POSIX-Standard dazu zu zitieren :
Dies ist genau der Teil der Shell-Grammatik
simple_command
Dies kommt von einem (simple_command → cmd_prefix → ASSIGNMENT_WORD). Wenn eine Zuweisung erfolgreich ist, ist der Exit-Status Null, es sei denn, es handelt sich um eine Befehlsersetzung. In diesem Fall ist der Exit-Status der Status des letzten. Wenn die Zuweisung fehlschlägt, ist der Exit-Status ungleich Null, aber Sie können ihn möglicherweise nicht abfangen.quelle
Du sagst,
Das ist keine schreckliche Sichtweise. Aber es ist eine leichte Vereinfachung. Der allgemeine Rückgabestatus von
ist der Exit-Status von . Die Zuweisung, die nach der Zuweisung erfolgt, setzt den Gesamt-Exit-Status nicht auf 0.cmd4
E=
D=
Auch, wie Ikarus weist darauf hin , können Variablen als nur lesbar gesetzt werden. Betrachten Sie die folgende Variation des Beispiels von icarus:
Obwohl
A
nur lesbar ist, führt bash den Befehl Substitution rechts vonA=
- und dann bricht den Befehl , daA
nur lesbar ist. Dies widerspricht weiter Ihrer Interpretation, dass der Exit-Wert der Zuordnung vor der rechten Seite der Zuweisung gilt.quelle