risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come rappresentare più condizioni in un'istruzione Shell se?

Voglio rappresentare più condizioni come questa:

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

ma quando eseguo la sceneggiatura, mostra

syntax error at line 15: `[' unexpected, 

dove la riga 15 è quella che mostra se .... 

Cosa c'è di sbagliato in questa condizione? Immagino che qualcosa non funzioni con ().

252
user389955

Tecnica classica (metacaratteri di fuga):

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

Ho incluso i riferimenti a $g tra virgolette; questa è una buona pratica, in generale. Rigorosamente, le parentesi non sono necessarie perché la precedenza di -a e -o la rende corretta anche senza di esse.

Si noti che gli operatori -a e -o fanno parte delle specifiche POSIX per test , aka [, principalmente per retrocompatibilità (poiché erano parte di test nella 7a edizione UNIX, ad esempio), ma sono esplicitamente contrassegnati come 'obsolescente' di POSIX. Bash (vedi espressioni condizionali ) sembra anticipare i significati classici e POSIX per -a e -o con i propri operatori alternativi che accettano argomenti.


Con un po 'di attenzione, puoi utilizzare l'operatore [[ più moderno, ma tieni presente che le versioni in Bash e Korn Shell (ad esempio) non devono essere identiche.

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

Esempio di esecuzione, utilizzando Bash 3.2.57 su 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

Non è necessario citare le variabili in [[ come si fa con [ perché non è un comando separato nello stesso modo in cui [ è.


Non è una domanda classica?

Lo avrei pensato Tuttavia, esiste un'altra alternativa, vale a dire:

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

In effetti, se leggi le linee guida della "shell portatile" per lo strumento autoconf oi pacchetti correlati, questa notazione, che usa "||" e "&&", è ciò che raccomandano. Suppongo che potresti persino spingermi oltre:

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

Dove le azioni sono banali come l'eco, questo non è male. Quando il blocco di azioni da ripetere è costituito da più righe, la ripetizione è troppo dolorosa e una delle versioni precedenti è preferibile oppure è necessario racchiudere le azioni in una funzione invocata nei diversi blocchi then.

317
Jonathan Leffler

In Bash:

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

Utilizzando /bin/bash il seguente funzionerà:

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

Fai attenzione se hai degli spazi nelle variabili stringa e controlli l'esistenza. Assicurati di citarli correttamente.

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