it-swarm.com.de

Wie repräsentiere ich mehrere Bedingungen in einer Shell-if-Anweisung?

Ich möchte mehrere Bedingungen wie folgt 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ührte, wird es angezeigt

syntax error at line 15: `[' unexpected, 

in Zeile 15 wird angezeigt, ob .... 

Was ist daran falsch? Ich denke, mit dem () stimmt etwas nicht.

252
user389955

Klassische Technik (Escape-Metazeichen):

if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi

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, weil -a und -o Vorrang haben, auch wenn sie vorkommen.

Beachten Sie, dass die Operatoren -a und -o Bestandteil der POSIX-Spezifikation für test , alias [ sind, hauptsächlich aus Gründen der Abwärtskompatibilität (da sie zum Beispiel in 7. Edition UNIX Bestandteil von test waren), sie jedoch ausdrücklich als gekennzeichnet sind "veraltet" von POSIX. Bash (siehe bedingte Ausdrücke ) scheint die klassische Bedeutung und die POSIX-Bedeutung von -a und -o mit eigenen alternativen Operatoren, die Argumente annehmen, zu unterdrücken.


Mit etwas 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.

for g in 1 2 3
do
    for c in 123 456 789
    do
        if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
        then echo "g = $g; c = $c; true"
        else echo "g = $g; c = $c; false"
        fi
    done
done

Beispiellauf mit Bash 3.2.57 unter Mac OS X:

g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false

Sie müssen die Variablen nicht wie in [[ in [ zitieren, da es sich nicht um einen separaten Befehl handelt, der in der gleichen Weise wie [ ist.


Ist das nicht eine klassische Frage?

Das hätte ich gedacht. Es gibt jedoch eine andere Alternative, nämlich:

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi

Wenn Sie die "Portable Shell" -Richtlinien für das autoconf-Tool oder die zugehörigen Pakete lesen, empfehlen sie diese Notation - mit "||" und "&&". Ich denke, Sie könnten sogar so weit gehen:

if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
Elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi

Wenn die Aktionen so trivial sind wie das Echo, ist das nicht schlecht. Wenn der zu wiederholende Aktionsblock mehrere Zeilen enthält, 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.

317

In Bash:

if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
151

Mit /bin/bash wird folgendes funktionieren:

if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
    echo "Entered $option"
fi
22
sunitha

Seien Sie vorsichtig, wenn Sie Leerzeichen in Ihren String-Variablen haben und nach Existenz suchen. Stellen Sie sicher, dass Sie sie richtig zitieren.

if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
7
orkoden
$ g=3
$ c=133
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
efg
$ g=1
$ c=123
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
abc
7
ghostdog74
#!/bin/bash

current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print $5'} )
echo $current_usage
critical_usage=6%
warning_usage=3%

if [[ ${current_usage%?} -lt ${warning_usage%?} ]]; then
echo OK current usage is $current_usage
Elif [[ ${current_usage%?} -ge ${warning_usage%?} ]] && [[ ${current_usage%?} -lt ${critical_usage%?} ]]; then
echo Warning $current_usage
else
echo Critical $current_usage
fi
0