it-swarm.com.de

Mehrere logische Operatoren ((A || B) && C) und "Syntaxfehler in der Nähe eines unerwarteten Tokens"

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 Bestrebungen 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 fuehrt zu:

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 fuehrt zu:

line 322: syntax error near unexpected token `[['

Ein Teil des Problems besteht darin, dass Suchergebnisse die trivialen Beispiele sind und nicht die komplexeren Beispiele mit zusammengesetzten Bedingungen.

Wie führe ich ein einfaches ((A || B) && C) in Bash?


Ich bin bereit, es einfach abzuwickeln 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
29
user56041

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 er funktioniert.

Der Hauptpunkt einer Shell ist das Ausführen von Befehlen. Der Open-Bracket-Befehl [ Ist ein Befehl, der einen einzelnen Test durchführt¹. Sie können es sogar als test schreiben (ohne die letzte schließende Klammer). Die Operatoren || Und && Sind Shell-Operatoren. Sie kombinieren Befehle und keine Tests.

Also wenn du schreibst

[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]

das ist analysiert als

[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]

das ist das gleiche 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 lautet geschweifte Klammern. Die Art und Weise, wie geschweifte Klammern analysiert werden, erfordert einen vollständigen Befehl vor ihnen. Daher müssen Sie den Befehl in den Klammern mit einem Zeilenumbruch oder einem 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 . In doppelten Klammern können Sie Klammern und Operatoren wie && Und || Verwenden. Da die doppelten Klammern Shell-Syntax sind, weiß die Shell, dass diese Operatoren, wenn sie sich in Klammern befinden, Teil der Syntax für bedingte Ausdrücke und nicht Teil der normalen Shell-Befehlssyntax sind.

if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …

Wenn alle Ihre Tests numerisch sind, gibt es noch einen anderen Weg, der artihmetische Ausdrücke abgrenzt. Arithmetische Ausdrücke führen ganzzahlige Berechnungen mit einer sehr C-ähnlichen Syntax durch.

if (((A == 0 || B != 0) && C == 0)); then …

Sie können meine Bash Bracket Primer nützlich finden.

[ Kann in normalem sh verwendet werden. [[ Und (( Sind spezifisch für Bash (und ksh und zsh).

¹ Es kann auch mehrere Tests mit booleschen Operatoren kombinieren, dies ist jedoch umständlich zu verwenden und weist subtile Fallstricke auf, sodass ich es nicht erklären werde.

Verwenden Sie [[:

if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ...

Wenn Sie [ Bevorzugen, funktioniert Folgendes:

if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ...
8
Stephen Kitt

Verwenden Sie den Operator -o Anstelle Ihres verschachtelten ||. Sie können auch -a Verwenden, um && zu ersetzen, falls dies in Ihren anderen Anweisungen erforderlich ist.

   EXPRESSION1 -a EXPRESSION2
          both EXPRESSION1 and EXPRESSION2 are true

   EXPRESSION1 -o EXPRESSION2
          either EXPRESSION1 or EXPRESSION2 is true


if [  "$A" -eq "0" -o "$B" -ne "0"  ] && [ "$C" -eq "0" ]; then echo success;fi
3
Zachary Brady