Ich möchte mehrere Bedingungen wie diese darstellen:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
aber wenn ich das Skript ausführe, zeigt es
syntax error at line 15: `[' unexpected,
wobei Zeile 15 diejenige ist, die zeigt, ob ....
Was ist falsch an dieser Bedingung? Ich denke, etwas stimmt nicht mit dem ()
.
test
([
) und nicht von der Shell ausgewertet . Die Shell wertet nur den Exit-Status von aus[
.Antworten:
Klassische Technik (Escape-Metazeichen):
Ich habe die Verweise auf
$g
in doppelte Anführungszeichen gesetzt; Das ist im Allgemeinen eine gute Praxis. Streng genommen werden die Klammern nicht benötigt, da sie Vorrang haben-a
und-o
auch ohne sie korrekt sind.Beachten Sie, dass die Operatoren
-a
und-o
Teil der POSIX-Spezifikationtest
sind[
, vor allem aus Gründen der Abwärtskompatibilität (da sie beispielsweise Teil dertest
7. Edition von UNIX waren), von POSIX jedoch ausdrücklich als "veraltet" gekennzeichnet werden. Bash (siehe bedingte Ausdrücke ) scheint die klassischen und POSIX-Bedeutungen für-a
und-o
mit eigenen alternativen Operatoren, die Argumente annehmen, zu verhindern.Mit einiger Sorgfalt können Sie den moderneren
[[
Operator verwenden. Beachten Sie jedoch, dass die Versionen in Bash und Korn Shell (zum Beispiel) nicht identisch sein müssen.Beispiellauf mit Bash 3.2.57 unter Mac OS X:
Sie brauchen nicht die Variablen in zitieren ,
[[
wie Sie mit zu tun ,[
weil es nicht ein separater Befehl in der gleichen Art und Weise, die[
ist.Das hätte ich mir gedacht. Es gibt jedoch eine andere Alternative, nämlich:
Wenn Sie die Richtlinien für tragbare Shell für das
autoconf
Tool oder verwandte Pakete lesen , wird diese Notation - mit '||
' und '&&
' - empfohlen. Ich nehme an, Sie könnten sogar so weit gehen:Wo die Aktionen so trivial sind wie Echo, ist das nicht schlecht. Wenn der zu wiederholende Aktionsblock aus mehreren Zeilen besteht, ist die Wiederholung zu schmerzhaft und eine der früheren Versionen ist vorzuziehen - oder Sie müssen die Aktionen in eine Funktion einschließen, die in den verschiedenen
then
Blöcken aufgerufen wird .quelle
-a
tatsächlich eine höhere Priorität haben als-o
(im Gegensatz zu&&
und||
in der Shell - innerhalb vonbash
[[ ... ]]
Bedingungen hat sie jedoch&&
auch eine höhere Priorität als||
). Wenn Sie vermeiden-a
und-o
für maximale Robustheit und Portabilität - was die POSIX-Manpage selbst vorschlägt - möchten, können Sie auch Subshells zum Gruppieren verwenden:if ([ $g -eq 1 ] && [ "$c" = "123" ]) || ([ $g -eq 2 ] && [ "$c" = "456" ])
if test "$g" -eq 1 -a "$c" = "123" || test "$g" -eq 2 -a "$c" = "456"; then ...
&&
oder||
auch vorzuziehen ist, da es sich eher wie Bedingungen in anderen Sprachen verhält und Sie Kurzschlussbedingungen ermöglicht. Zum Beispiel :if [ -n "${check_inodes}" ] && [ "$(stat -f %i "/foo/bar")" = "$(stat -f %i "/foo/baz")" ]
. Wenn Sie dies auf diese Weise tuncheck_inodes
, vermeiden Sie zwei Aufrufe vonstat
, während eine größere, komplexe Testbedingung vor der Ausführung alle Argumente verarbeiten muss (was auch zu Fehlern führen kann, wenn Sie dieses Verhalten vergessen).In Bash:
quelle
bash
. Nebenbei: In diesem speziellen Fall werden die Klammern nicht einmal benötigt, da innere[[ ... ]]
Bedingungen&&
tatsächlich eine höhere Priorität haben als||
- im Gegensatz zu solchen äußeren Bedingungen.if
/ -Anweisung trennenelse
und den Code zwischenthen
undfi
eine Funktion einfügen , um eine Wiederholung zu vermeiden. In sehr einfachen Fällen können Sie einecase
Anweisung mit;&
Fallthrough verwenden (in Bash 4).Die Verwendung
/bin/bash
der folgenden Funktionen funktioniert:quelle
Seien Sie vorsichtig, wenn Ihre Zeichenfolgenvariablen Leerzeichen enthalten und Sie auf Existenz prüfen. Stellen Sie sicher, dass Sie sie richtig zitieren.
quelle
quelle
{ ;}
könnte stattdessen verwendet werden.In Bash für den Zeichenfolgenvergleich können Sie die folgende Technik verwenden.
Beispiel:
quelle
quelle
Sie können auch mehr als 2 Bedingungen verketten:
quelle