Bash if declaração com várias condições gera um erro

165

Estou tentando escrever um script que irá verificar dois sinalizadores de erro e, caso um sinalizador (ou ambos) sejam alterados, ele ecoará - ocorreu um erro. Meu script:

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

Basicamente, deve haver algo junto:

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

O erro que recebo é:

 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'

Meus suportes estão bagunçados?

Simplesmente eu
fonte
2
Use parênteses - ()
AlikElzin-kilaka
3
Logicamente, a==1 or b==2já cobre o caso em que a==1 and b==2. Testar separadamente para isso é completamente supérfluo aqui.
01

Respostas:

248

Use -a(para e) e -o(para ou) operações.

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

Atualizar

Na verdade, você ainda pode usar &&e ||com a -eqoperação. Portanto, seu script seria assim:

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

Embora no seu caso você possa descartar as duas últimas expressões e ficar com uma ou operação como esta:

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
mkhatib
fonte
3
@Simply_Me: Não, um OR lógico é verdadeiro se um ou ambos os seus operandos forem verdadeiros. Você está pensando em "exclusivo ou" (XOR), o que é verdadeiro se exatamente um de seus operandos for verdadeiro. (Na verdade, existem versões de XOR que o trabalho de mais de 2 operandos, caso em que ele é verdadeiro se um número ímpar de operandos são verdadeiras.)
Gordon Davisson
4
BTW, os problemas no código original incluem o uso [e o ]agrupamento (eles não fazem isso) e a falha em colocar espaços ao redor do operador (por exemplo "$my_error_flag"="1"), o que impede que o shell o reconheça como um operador. Leia BashFAQ # 17 (no agrupamento) e # 31 (sobre a diferença entre diferentes tipos de expressão de teste) . Na verdade, nesse caso, seria ainda mais fácil usar uma expressão aritmética .
Gordon Davisson
7
-ae -osão considerados obsoletos pela especificação POSIX ; use testes separados combinados com ||os da atualização.
chepner
1
Não há necessidade de agrupar usando subshells, normalmente o agrupamento usando {}também deve ser possível.
Phk
1
para adicionar ao comentário do phk acima, () está lançando sub-shell no bash, que pode ter todos os tipos de efeitos sutis (provavelmente indesejados).
Brett
70

Você pode usar uma das palavras-chave [[ou ((. Quando você usa [[palavras-chave, você tem que operadores de string uso, como -eq, -lt. Eu acho que ((é o mais preferido para aritmética, porque você pode usar diretamente operadores como ==, <e >.

Usando [[operador

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

Usando ((operador

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

Não use -aou -ooperadores, pois não é portátil.

Fizer Khan
fonte
8

Por favor, tente seguir

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!"
Manash Nath
fonte
2
( ... )cria subcascas - muito impacto no desempenho, sem nenhum benefício.
Charles Duffy
4
Use { ...; }para agrupar sem criação de subcasca.
Charles Duffy
1

Você pode se inspirar lendo um entrypoint.sh script escrito pelos colaboradores do MySQL que verifica se as variáveis ​​especificadas foram definidas.

Como o script mostra, você pode canalizá-los com -a, por exemplo:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi
Daniel Andrei Mincă
fonte
1
-aestá marcado como obsoleto na versão atual do testpadrão POSIX ; veja os OBmarcadores em pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Use [ -z "$FOO" ] && [ -z "$BAR" ]para ter um código mais confiável.
Charles Duffy