Gibt es einen Unterschied zwischen '&&' und ';' Symbole in einem Standard-BASH-Terminal?

56

Beide scheinen BASH zu signalisieren, mit einem anderen Befehl zu beginnen, der den Symbolen folgt. Gibt es jedoch einen deutlichen Unterschied?

Michael Terry
quelle

Antworten:

75

Mit dieser Zeile:

command1 && command2

Befehl2 wird ausgeführt, wenn (und nur wenn) Befehl1 den Exit-Status Null zurückgibt, wobei in dieser Zeile:

command1 ; command2

Befehl1 und Befehl2 werden unabhängig voneinander ausgeführt. Mit dem Semikolon können Sie viele Befehle in einer Zeile eingeben.


quelle
1
Interessant! Ich hatte geglaubt, es sei vielleicht bequemer. Danke!
42

Sie können den Unterschied selbst ausprobieren:

  1. ls /invalid/path && echo "hello!"
    Da / invalid / path nicht existiert, kann ls die Verzeichnisliste nicht anzeigen. Es wird mit einer Fehlermeldung fehlschlagen: "ls: / invalid / path: Keine solche Datei oder Verzeichnis".
    Die zweite Hälfte des Befehls (Echo "Hallo!") Wird nie ausgeführt, da die erste Hälfte fehlgeschlagen ist.

  2. ls /invalid/path ; echo "hello!"
    Es erscheint die gleiche Fehlermeldung wie zuvor, diesmal wird jedoch der zweite Teil ausgeführt !
    ls: / invalid / path: Keine solche Datei oder Verzeichnis
    hallo!

Warum ist das nützlich?
Angenommen, Sie möchten eine Datei mit dem Namen archive.tar.gz extrahieren.
Sie könnten den Befehl verwenden tar zxvf archive.tar.gz && rm archive.tar.gz.
Wenn das Extrahieren des Archivs aus irgendeinem Grund fehlschlägt, wird der zweite Teil nicht ausgeführt! Sie können es erneut versuchen.

Wenn du benutzt ; In der gleichen Situation wird das Archiv gelöscht und Sie können es nicht erneut versuchen.

Kenny Rasschaert
quelle
8

&&ist AND, was bedeutet, dass der zweite Befehl nur ausgeführt wird, wenn der erste true zurückgegeben hat (keine Fehler).

Ward Muylaert
quelle
1
&& ist ein "dann" (kein "und") ... siehe meine Antwort
Peter.O
2
@fred Ich würde sagen, es ist ein "und" mit Kurzschlussauswertung - wenn der erste Teil nicht wahr ist, weiß es, dass das Gesamtergebnis falsch sein muss, sodass der zweite Teil übersprungen wird. Aber stimmen Sie zu, dass es in diesem Zusammenhang kaum einen Unterschied macht, wenn man es als "dann" betrachtet.
jg-faustus
2
@fred Obwohl es konzeptionell vielleicht einfacher ist, es so zu verstehen, stimme ich Ihrer Aussage nicht zu. Die Idee ist einfach, dass bei jeder AND Ausführung der 2. Parameter irrelevant wird, wenn der erste gleich ist, falseund so der zugrunde liegende Code optimiert wird, um die Bewertung des 2. Parameters zu verschieben, bis er weiß, was der erste ist.
Ward Muylaert
2
@fred Ich bin mir nicht sicher, welchen Punkt dieses Beispiel machen soll. &&ist nur ein binärer Operator, eine Funktion. Das einzige "Besondere" ist, dass es sich um die Infixnotation (die ohnehin für die meisten dieser Operatortypen Standard ist) und die verzögerte Ausführung des zweiten Operanden handelt. Die verzögerte Ausführung gibt ihm in der Tat die Fähigkeit , als etwas zu verwenden , die vom Konzept her als betrachtet werden können ifAussage in diesem Zusammenhang , aber das dauert nicht weg von der Tatsache , dass es ursprünglich Nutzung bestimmt ist , ist innerhalb der bedingten einer tatsächlichen ifAnweisung. Die Verwendung hier ist wirklich eher ein "Hack".
Ward Muylaert
3
@fred Natürlich ist es kein ternärer Operator, sondern nur die Folge von zwei Operationen a && b || c = (a && b) || c. Einfache Reihenfolge der Auswertung. Da gibt es wirklich kein Geheimnis. Wenn Sie sie wie Ihre typischen Funktionen schreiben würden, würde es einfach so aussehen or(and(a, b), c). Diese Logik ist die gleiche innerhalb einer ifbedingten sowie , wenn es direkt in die Befehlszeile eingeben , da &&und ||sind Operatoren , sie umfassen zwei Operanden und sie kehren anderen.
Ward Muylaert
8

Update : Ich habe einige der möglichen Fallen als Skript hinzugefügt:

Weil sonst niemand "||" erwähnt hat, werde ich

Update2 : Einige wichtige Umformulierungen hier
&& sind wie ein "dann" einer "wenn" -Anweisung, die auf "wahr" reagiert.

|| ist NICHT wie das "else" einer "if" -Anweisung ..
|| ist wie ein "dann" einer "wenn" -Anweisung, die auf "falsch" reagiert

Genauer gesagt, testet && das $? Rückgabewert der vorherigen zuletzt ausgeführten Anweisung und übergibt die Steuerung an der Anweisung oder Unterschale unmittelbar nach dem && ... es geht nur die Kontrolle , wenn $? ist wahr.

|| ähnlich ist, und wird häufig nach einer && Anweisung gesehen, aber es testet für einen falschen Rückgabewert ($?) von der vorherigen zuletzt ausgeführten Anweisung ... NB! , Nota Bene! Gut zu beachten! .... wenn die vorhergehende Anweisung eine &&-Anweisung ist, die false wiederholt, wenn Sie erwarten, dass es true ist, dann || wird auf false reagieren, daher kann es riskant sein, beide in derselben Zeile zu mischen

Der Hauptgrund, den ich zu machen versuche, ist in Bezug auf einen Fehler, den ich gemacht habe. dh:
## [[Bedingung]] && A || B
ist nicht benimmt sich nicht wie ein C / C ++ Stil ternäre. dh:
// (Bedingung)? A: B
Im folgenden Skript finden Sie Beispiele für "unerwartete" Ergebnisse von "A".

Der Basistest und das && und das || Anweisung muss alle in der gleichen Zeile sein ...


Führen Sie dieses Skript aus, um festzustellen, wo bei Verwendung von && und || Probleme auftreten können
Die zuletzt ausgeführte Anweisung ist möglicherweise nicht die erwartete.

[[Bedingung]] && echo Hallo || echo Goodbye .... ist normalerweise sicher,
da ein gut geformtes Echo true zurückgibt.
aber was ist mit dem Zugriff auf eine Datei, die nicht existiert?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 

Peter.O
quelle
1

Versuchen

falsch && echo "hallo"

und

falsch; Echo "Hallo"

sieh den Unterschied

Petrie Wong
quelle
0

Der Befehl (Funktion im Falle eines Skripts) danach &&wird abhängig vom RETVAL des ersten Befehls (Funktion im Falle eines Skripts) ausgeführt. Erzwingt bei Erfolg, dass der erste Befehl den Wert 0 zurückgibt. Wir können den Rückgabewert überprüfen, um weitere Befehle auszuführen.

theTuxRacer
quelle