Ich lerne über Entscheidungsstrukturen und bin auf folgende Codes gestoßen:
if [ -f ./myfile ]
then
cat ./myfile
else
cat /home/user/myfile
fi
[ -f ./myfile ] &&
cat ./myfile ||
cat /home/user/myfile
Beide verhalten sich gleich. Gibt es irgendwelche Vorteile, wenn man den einen Weg vom anderen benutzt?
shell-script
syntax
control-flow
Subhaa Chandar
quelle
quelle
Antworten:
Nein, Konstruktionen
if A; then B; else C; fi
undA && B || C
sind nicht gleichwertig .Mit
if A; then B; else C; fi
wird der BefehlA
immer ausgewertet und ausgeführt (es wird zumindest versucht, ihn auszuführen) und dann werden entweder der BefehlB
oder der BefehlC
ausgewertet und ausgeführt.Mit
A && B || C
ist es für Befehle gleichA
undB
fürC
: BefehlC
wird ausgewertet und ausgeführt, wenn entwederA
fehlschlägt oderB
fehlschlägt.Nehmen wir in Ihrem Beispiel an , Sie werden es
chmod u-r ./myfile
trotz[ -f ./myfile ]
Erfolg tuncat /home/user/myfile
Mein Rat: Verwenden Sie
A && B
oderA || B
alles, was Sie wollen, dies bleibt leicht zu lesen und zu verstehen und es gibt keine Falle. Aber wenn du meinst, wenn ... dann ... sonst ... dann benutzeif A; then B; else C; fi
.quelle
Die meisten Menschen finden es einfacher , das zu verstehen
if
...then
...else
...fi
Form.Für die
a && b || c
muss man sicher sein, dassb
true zurückgegeben wird. Dies ist eine Ursache für subtile Fehler und ein guter Grund, diesen Stil zu vermeiden. Wenn b nicht true zurückgibt, sind diese nicht gleich.Für sehr kurze Tests und Aktionen, die keine else-Klausel enthalten, ist die verkürzte Länge attraktiv, z
&&
und||
werdenshort circuiting operators
, sobald das Ergebnis bekannt ist, weitere nicht benötigte Tests übersprungen.a && b || c
ist gruppiert als(a && b) || c
. Zuersta
wird ausgeführt. Wenn esfails
so definiert ist, dass es keinen Exit-Status von 0 zurückgibt, ist die Gruppe(a && b)
bekanntfail
undb
muss nicht ausgeführt werden. Der||
kennt das Ergebnis des Ausdrucks nicht, muss also ausgeführt werdenc
. Wenn diesa
erfolgreich ist (Null zurückgibt),&&
weiß der Bediener das Ergebnis noch nicht unda && b
muss es erst ausführenb
, um es herauszufinden. Wenn diesb
gelingt, ist diesa && b
erfolgreich und das||
Gesamtergebnis lautet "Erfolg". Sie müssen nicht ausgeführt werdenc
. Wennb
dann fehlschlägt||
kennt den Wert des Ausdrucks noch nicht, muss also ausgeführt werdenc
.quelle
Der Operator && führt den nächsten Befehl aus, wenn der vorherige Befehl erfolgreich ausgeführt wurde (zurückgegebener Exit-Code ($?) 0 = logisch wahr).
In Form
A && B || C
wird der Befehl (oder die Bedingung) A ausgewertet, und wenn A true zurückgibt (Erfolg, Beendigungscode 0), wird der Befehl B ausgeführt. Wenn A fehlschlägt (so kehrt falsche - Beendigungscode ungleich 0) und / oder B fehlschlägt (Rückkehr falsch ) , dann Befehl C wird ausgeführt.Der
&&
Operator wird auch als UND in Bedingungsprüfungen verwendet, und der Operator||
arbeitet wie ODER in Bedingungsprüfungen.Abhängig davon, was Sie mit Ihrem Skript tun möchten,
A && B || C
kann form für Bedingungsprüfungen wie in Ihrem Beispiel verwendet werden oder zum Verketten von Befehlen und zum Ausführen einer Reihe von Befehlen, wenn vorherige Befehle den erfolgreichen Beendigungscode 0 hatten .Aus diesem Grunde ist es üblich , Befehle zu sehen , wie:
do_something && do_something_else_that_depended_on_something
.Beispiele:
apt-get update && apt-get upgrade
Wenn das Update fehlschlägt, wird das Upgrade nicht ausgeführt (in der Praxis sinnvoll ...).mkdir test && echo "Something" > test/file
Der Teil
echo "Something"
wird nur ausgeführt, wenn dermkdir test
Vorgang erfolgreich war und der Beendigungscode 0 zurückgegeben wurde ../configure --prefix=/usr && make && sudo make install
Wird normalerweise beim Kompilieren von Jobs zum Verketten der erforderlichen abhängigen Befehle verwendet.
Wenn Sie versuchen , über „Ketten“ mit zu implementieren , wenn - dann - sonst müssen Sie viel mehr Befehle und überprüft (und damit mehr Code zu schreiben - mehr Dinge schief gehen) für eine einfache Aufgabe.
Beachten Sie auch, dass Befehle mit && und || verkettet sind werden von Shell von links nach rechts gelesen. Möglicherweise müssen Sie Befehle und Bedingungsprüfungen in Klammern gruppieren, um den nächsten Schritt von der erfolgreichen Ausgabe einiger vorheriger Befehle abhängig zu machen. Zum Beispiel siehe dies:
Oder ein reales Beispiel:
Beachten Sie, dass einige Befehle verschiedenen Exit - Codes in Abhängigkeit von dem Prozess ausgeführt zurückzukehren, oder kehren verschiedene Codes in Abhängigkeit von ihren Aktionen (zum Beispiel Befehl GNU
diff
, kehren 1 , wenn zwei Dateien unterscheiden, und 0 , wenn sie es nicht tun). Solche Befehle müssen in && und || mit Sorgfalt behandelt werden .Beachten Sie auch die Verkettung von Befehlen mithilfe des
;
Operators , um alle Rätsel zusammen zu haben . Bei einem Format werdenA;B;C
alle Befehle unabhängig vom Exit-Code von commandA
und in Serie ausgeführtB
.quelle
Ein Großteil der Verwirrung darüber kann auf die Bash-Dokumentation zurückzuführen sein, die diese UND- und ODER-Listen aufruft . Während logisch ähnlich dem
&&
und||
in eckigen Klammern gefunden, funktionieren sie anders.Einige Beispiele mögen dies am besten veranschaulichen ...
Wenn
cmda
exit true ist,cmdb
wird ausgeführt.Wenn
cmda
exit falsch ist,cmdb
wird NICHT ausgeführt, ist abercmdc
.Wie
cmda
Ausgänge wird ignoriert.Wenn
cmdb
exit true ist,cmdc
wird ausgeführt.Wenn
cmdb
exit falsch ist,cmdc
wird NICHT ausgeführt undcmdd
ist.Wenn
cmda
exit true ist,cmdb
wird ausgeführt, gefolgt voncmdc
.Wenn
cmda
exit falsch ist,cmdb
wird es NICHT ausgeführt ,cmdc
ist es aber .Huh? Warum wird
cmdc
ausgeführt?Für den Interpreten
;
bedeuten ein Semikolon ( ) und ein Zeilenumbruch genau dasselbe. Bash sieht diese Codezeile als ...Um das zu erreichen, was erwartet wird, müssen wir
cmdb; cmdc
geschweifte Klammern einschließen , um sie zu einem zusammengesetzten Befehl (Gruppenbefehl) zu machen . Das zusätzliche abschließende Semikolon ist nur eine Anforderung der{ ...; }
Syntax. Also bekommen wir ...cmda && { cmdb; cmdc; }
Wenn
cmda
exit true ist,cmdb
wird ausgeführt, gefolgt voncmdc
.Wenn
cmda
false beendet wird, wird wedercmdb
nochcmdc
ausgeführt.Die Ausführung wird mit der nächsten Zeile fortgesetzt.
Verwendung
Bedingte Befehlslisten sind am nützlichsten, um Funktionen so schnell wie möglich zu verlassen und so zu vermeiden, dass unnötiger Code interpretiert und ausgeführt wird. Mehrfache Funktionsrückgaben bedeuten jedoch, dass man die Funktionen unbedingt kurz halten muss, damit leichter sichergestellt werden kann, dass alle möglichen Bedingungen erfüllt sind.
Hier ist ein Beispiel aus einem laufenden Code ...
quelle