Bash if L'istruzione con più condizioni genera un errore


165

Sto provando a scrivere uno script che controllerà due flag di errore e, nel caso in cui uno sia cambiato (o entrambi), verrà ripetuto l'errore. La mia sceneggiatura:

my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" &&     "$my_error_flag_o"="2" ]]; then
    echo "$my_error_flag"
else
    echo "no flag"
fi

Fondamentalmente, dovrebbe essere, qualcosa lungo:

if ((a=1 or b=2) or (a=1 and b=2))
  then
     display error
else
     no error
fi

L'errore che ottengo è:

 line 26: conditional binary operator expected
 line 26: syntax error near `]'
 line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'

Le mie parentesi sono incasinate?



2
Usa le parentesi - ()
AlikElzin-kilaka il


3
Logicamente, a==1 or b==2già copre il caso in cui a==1 and b==2. Test separatamente per questo è completamente superfluo qui.
Tripleee,

Risposte:


249

Utilizzare le operazioni -a(per e) e -o(per o).

tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

Aggiornare

In realtà potresti ancora usare &&e ||con l' -eqoperazione. Quindi la tua sceneggiatura sarebbe così:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
      echo "$my_error_flag"
else
    echo "no flag"
fi

Sebbene nel tuo caso puoi scartare le ultime due espressioni e attenersi a una o a un'operazione come questa:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ]; then
      echo "$my_error_flag"
else
    echo "no flag"
fi

3
@Simply_Me: No, un OR logico è vero se uno o entrambi i suoi operandi sono veri. Stai pensando a "esclusivo o" (XOR), il che è vero se esattamente uno dei suoi operandi è vero. (In realtà, ci sono versioni di XOR che funzionano su più di 2 operandi, nel qual caso è vero se un numero dispari di operandi è vero.)
Gordon Davisson

4
A proposito, i problemi nel codice originale includono l'uso [e il ]raggruppamento (non lo fanno) e il mancato posizionamento degli spazi attorno all'operatore (ad esempio "$my_error_flag"="1"), che impedisce alla shell di riconoscerlo come operatore. Leggere BashFAQ # 17 (sul raggruppamento) e # 31 (sulla differenza tra i diversi tipi di espressione del test) . In realtà, in questo caso sarebbe ancora più semplice usare un'espressione aritmetica .
Gordon Davisson,

7
-ae -osono considerati obsoleti dalla specifica POSIX ; utilizzare test separati combinati con ||come nell'aggiornamento.
chepner,

1
Non è necessario raggruppare usando i subshells, normalmente {}dovrebbe anche essere possibile raggruppare usando .
phk,

1
per aggiungere al commento di phk sopra, () sta lanciando subshells in bash, che può avere tutti i tipi di effetti sottili (probabilmente indesiderati).
Brett

70

Puoi usare una [[o una ((parola chiave. Quando si utilizza [[parola chiave, è necessario operatori utilizzo stringa come -eq, -lt. Penso che ((sia più preferito per l'aritmetica, perché puoi usare direttamente operatori come ==, <e >.

Utilizzando l' [[operatore

a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
     echo "Error"
else
     echo "No Error"
fi

Utilizzando l' ((operatore

a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
     echo "Error"
else
     echo "No Error"
fi

Non utilizzare -ao -ooperatori Dal momento che non è portatile.


8

Per favore prova a seguire

if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
    echo "WORKING"
else
    echo "Out of range!"

2
( ... )crea sottotitoli: un sacco di impatto sulle prestazioni senza alcun vantaggio.
Charles Duffy,

4
Utilizzare { ...; }per il raggruppamento senza la creazione di subshell.
Charles Duffy,

1

Puoi trarre ispirazione leggendo uno entrypoint.sh script scritto dai contributori di MySQL che controlla se sono state impostate le variabili specificate.

Come mostra lo script, puoi eseguirne il pipe -a, ad esempio:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi

1
-aè contrassegnato come obsoleto nella versione corrente dello teststandard POSIX ; vedere gli OBindicatori su pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Utilizzare [ -z "$FOO" ] && [ -z "$BAR" ]per avere un codice più affidabile.
Charles Duffy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.