Vorrang logischer Operatoren gegenüber Semikolon

7

Was passiert, wenn ich eine Zeile wie Bash schreibe?

commandA && commandB ; commandC

Wenn commandAfehlschlägt, wird commandCausgeführt?

user20273
quelle
Nur für den Fall, dass Sie beides wollen commandBund commandC(wenn es commandAin Ordnung ist), schreiben commandA && (commandB ; commandC )
Sie

Antworten:

10

Ja, und Sie können es ganz einfach selbst überprüfen:

$ non-existent-command && echo hi ; echo after semicolon
bash: non-existent-command: command not found
after semicolon

Darin man bashsteht:

Befehle getrennt durch a; werden nacheinander ausgeführt; Die Shell wartet darauf, dass jeder Befehl nacheinander beendet wird.

Arkadiusz Drabczyk
quelle
3

commandCwird ausgeführt, egal ob commandAodercommandB fehlschlägt oder erfolgreich ist.

Semikolon ist nur ein Trennzeichen, mit dem Befehle nacheinander ausgeführt werden können. Das Szenario nur , dass ich kann sehen , wo commandCfehlschlagen, ist , wenn commandAoder commandBsind exitBefehle (oder irgendein Befehl wie return/ break/ continue/exec (oder Funktionen , die diejenigen nennen) das wirkt sich gewaltsam den Arbeitsablauf):

Szenario 1: commandAistexit

[root@host ~]# exit && echo "HI"; echo "test"
logout
[user@host ~]$

Szenario 2: commandBistexit

[root@host~]# echo "HI" && exit; echo "test"
HI
logout
[user@host ~]$

tl; dr: Ist das nicht so, dass diese Zeichen Vorrang haben? Sie bedeuten verschiedene Dinge. Einer ist ein logischer Operator und der andere ist ein Listenabschluss.

Verwandte Sachen:

  • Was sind die Steuerungs- und Umleitungsoperatoren der Shell?  Diese Antwort gibt eine gute Erklärung für die Bash-Operatoren. Ein kleines Stück der Antwort zitieren:

    • ; : Führt einen Befehl nach dem anderen aus, unabhängig vom Ergebnis des ersten.

      command1 ; command2

      Zuerst command1wird im Vordergrund ausgeführt, und sobald es fertig ist, command2 wird es ausgeführt.

      Eine neue Zeile, die nicht in einem Zeichenfolgenliteral oder nach bestimmten Schlüsselwörtern steht , entspricht nicht dem Semikolonoperator. Eine Liste mit ;begrenzten einfachen Befehlen ist immer noch eine Liste - wie im Parser der Shell müssen die einfachen Befehle, die einem ; begrenzten einfachen Befehl folgen, vor der Ausführung weiterhin eingelesen werden , während eine neue Zeile eine gesamte Befehlsliste oder Liste von Listen begrenzen kann. Der Unterschied ist subtil, aber kompliziert: Da die Shell keine vorherige Notwendigkeit zum Einlesen von Daten nach einer neuen Zeile hat, markiert die neue Zeile einen Punkt, an dem die Shell beginnen kann, die einfachen Befehle auszuwerten, die sie bereits eingelesen hat, während ein ;Semikolon dies tut nicht.

  • Semikolons am Ende einer Zeile in Shell-Skripten überflüssig?   Zitiert die Antwort:

    Einzelne Semikolons am Ende einer Zeile sind überflüssig, da die neue Zeile auch ein Befehlstrennzeichen ist. casebenötigt speziell doppelte Semikolons am Ende des letzten Befehls in jedem Musterblock; siehe help casefür Details.

  • Was ist der Unterschied zwischen Semikolon und doppeltem kaufmännischem Und &&


quelle
1
Was meinst du mit "Haben diese Charaktere nicht Vorrang?"? &&(und ||) haben eine höhere Priorität als ;(und |). Was meinst du mit "Einer dient zum Vergleich und der andere soll abgrenzen, wo der nächste Befehl in einer Liste von Befehlen beginnen wird (Steueroperator)."? Sie sind alle Steuerungsoperatoren; Sie alle begrenzen einfache Befehle.
G-Man sagt "Reinstate Monica"
Die Verwirrung wurde behoben: Einer ist ein logischer Operator, während der andere ein Listenabschluss ist, die beide Steueroperatoren sind. Aber sie haben überhaupt keinen "Vorrang", da ;sie unabhängig vom Ergebnis dessen, was noch übrig ist, ausgeführt werden. Es ist ein Trennzeichen wie newlinebei Shell-Skripten, und sein Lesen ähnelt irgendwie dem natürlichen Lesen: erste Befehlszeilensequenz ;zweite Befehlszeilensequenz ;dritte Befehlszeilensequenz ;usw.
1

per Bash-Manpage

[L] ist Operatoren, && und || haben den gleichen Vorrang, gefolgt von; und &, die den gleichen Vorrang haben.

In der Praxis läuft dies darauf hinaus, wer sich um das Renditeergebnis kümmert. Wenn das Ergebnis sofort benötigt wird, hat es eine höhere Priorität.

hildred
quelle
1

Wie andere Beiträge bereits sagten, lautet die kurze Antwort "Ja, commandCwird ausgeführt, unabhängig davon, was sonst noch passiert."

Wie nwildner untersucht hat , lautet die längere Antwort: „Ja, commandCwird ausgeführt, unabhängig davon, was sonst noch passiert, solange sich die Shell noch in einem Zustand befindet, in dem sie ausgeführt werden kann commandC. Mit anderen Worten, die Shell wird nicht über das hinausgehen

commandA && commandB ; command

Befehlszeile ohne Ausführung commandC. "

Wenn commandA(oder commandB) kill -KILL $$ etwas anderes ist, das die Shell beendet oder lähmt oder den Befehlsfluss stört, commandCwird es nicht ausgeführt. (Es handelt sich hier eindeutig um Randfälle.) Das Verhalten ist etwas anders, wenn set -e (oder gleichwertig set -o errexit) Folgendes ausgegeben wurde:

  • Wenn dies commandAfehlschlägt, commandCwird es ausgeführt (wird es aber commandBnicht sein).
  • Wenn dies commandAerfolgreich ist, commandBwird es ausgeführt.
    • Wenn dies commandBerfolgreich ist, commandCwird es ausgeführt.
    • Wenn commandBnicht, wird die Shell verlassen, und commandCwird nicht ausgeführt werden.

Die errexitOption gibt an, dass die Shell beendet werden soll, wenn ein Befehl (eine „Pipeline“) fehlschlägt, mit einigen Ausnahmen:

Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf ein whileoder ein untilSchlüsselwort folgt , Teil des Tests, der den ifoder elifreservierten Wörtern folgt , Teil eines Befehls, der in einer &&oder ||-Liste ausgeführt wird, mit Ausnahme des Befehls, der auf das letzte &&oder ein ||beliebiges folgt Befehl in einer Pipeline, aber der letzte, oder wenn der Rückgabewert des Befehls mit invertiert wird! .

- von Bash (1)

Wenn dies commandAfehlschlägt, wird dies nur commandBnicht ausgeführt, da commandAgefolgt wird &&. Wenn es jedoch ausgeführt wird commandBund fehlschlägt, wird die Shell beendet, da es ( commandB) dem (final) folgt &&.

G-Man sagt "Reinstate Monica"
quelle