Ich arbeite mit Bash 3 und versuche, eine Bedingung zu bilden. In C/C++ ist es ganz einfach:((A || B) && C)
. In Bash stellt sich heraus, dass dies nicht der Fall ist (ich denke, die Git-Autoren müssen diesen Code beigesteuert haben, bevor sie sich anderen Unternehmungen zuwandten).
Das funktioniert nicht. Beachten Sie, dass <0 or 1>
ist kein String-Literal; es bedeutet eine 0 oder 1 (kommt im Allgemeinen von grep -i
).
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi
Es ergibt sich:
line 322: syntax error near unexpected token `[['
Ich habe dann versucht:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi
es resultiert in:
line 322: syntax error near unexpected token `[['
Ein Teil des Problems besteht darin, dass die Suchergebnisse triviale Beispiele sind und nicht die komplexeren Beispiele mit zusammengesetzten Bedingungen.
Wie führe ich einen einfachen ((A || B) && C)
durch in Bash?
Ich bin bereit, es einfach auszurollen und dieselben Befehle in mehreren Blöcken zu wiederholen:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then
...
elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then
...
fi
Akzeptierte Antwort:
Die Syntax von Bash ist nicht C-ähnlich, auch wenn ein kleiner Teil davon von C inspiriert ist. Sie können nicht einfach versuchen, C-Code zu schreiben und erwarten, dass es funktioniert.
Der Hauptzweck einer Shell besteht darin, Befehle auszuführen. Der Befehl zum Öffnen der Klammer [
ist ein Befehl, der einen einzelnen Test durchführt¹. Sie können es sogar als test
schreiben (ohne die abschließende Klammer). Der ||
und &&
Operatoren sind Shell-Operatoren, sie kombinieren Befehle , keine Tests.
Also, wenn Sie schreiben
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]
das wird geparst als
[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]
was dasselbe ist wie
test [ "$A" -eq "0" ||
test "$B" -ne "0" ] &&
test "$C" -eq "0"
Beachten Sie die unausgeglichenen Klammern? Ja, das ist nicht gut. Ihr Versuch mit Klammern hat das gleiche Problem:falsche Klammern.
Die Syntax zum Gruppieren von Befehlen ist geschweiften Klammern. Die Art und Weise, wie geschweifte Klammern analysiert werden, erfordert einen vollständigen Befehl vor ihnen, also müssen Sie den Befehl innerhalb der geschweiften Klammern mit einem Zeilenumbruch oder Semikolon beenden.
if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then …
Es gibt eine alternative Möglichkeit, doppelte Klammern zu verwenden. Im Gegensatz zu einfachen Klammern sind doppelte Klammern eine spezielle Shell-Syntax. Sie begrenzen bedingte Ausdrücke. Innerhalb doppelter Klammern können Sie Klammern und Operatoren wie &&
verwenden und ||
. Da die doppelten Klammern Shell-Syntax sind, weiß die Shell, dass diese Operatoren, wenn sie in Klammern stehen, Teil der Syntax bedingter Ausdrücke sind, nicht Teil der normalen Shell-Befehlssyntax.
if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …
Wenn alle Ihre Tests numerisch sind, gibt es noch eine andere Möglichkeit, arithmetische Ausdrücke abzugrenzen. Arithmetische Ausdrücke führen ganzzahlige Berechnungen mit einer sehr C-ähnlichen Syntax durch.
if (((A == 0 || B != 0) && C == 0)); then …
Vielleicht finden Sie meine Bash-Klammer-Grundierung nützlich.
Siehe auch:Debian – Systemabsturz – seltsame Zeichen im Syslog?
[
kann in schlichtem sh verwendet werden. [[
und ((
sind spezifisch für bash (und ksh und zsh).
¹ Es kann auch mehrere Tests mit booleschen Operatoren kombinieren, aber dies ist umständlich zu verwenden und hat subtile Fallstricke, sodass ich es nicht erklären werde.