sh AND e OR em um comando

3

Tentando verificar três condições em uma linha de código, mas estou preso.

Essencialmente, eu preciso codificar o seguinte:

IF

string1 is not equal to string2

AND

string3 is not equal to string4

OR

bool1 = true

THEN

display "conditions met - running code ...".

Conforme solicitado nos comentários, atualizei meu exemplo para tentar esclarecer o problema.

#!/bin/sh

string1="a"
string2="b"
string3="c"
string4="d"
bool1=true

# the easy-to-read way ....
if [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] ; then
    echo "conditions met - running code ..."
fi

if $bool1 ; then
    echo "conditions met - running code ..."
fi

# or the shorter way ...
[ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] && echo "conditions met - running code ..."

$bool1 && echo "conditions met - running code ..."

O código acima será potencialmente executado duas vezes: se as duas primeiras condições forem atendidas e, novamente, se a terceira condição for atendida. Isso não é o que eu preciso.

A questão com este exemplo é que envolve 2 chamadas distintas para 'echo' - (note: no código real, não é um eco, mas você tem a ideia). Eu estou tentando reduzir a duplicação de código combinando a verificação de condição 3 em um único comando.

Tenho certeza de que algumas pessoas agora estão balançando a cabeça e gritando na tela "Isso é NÃO como você faz isso!"

E há provavelmente outros esperando para marcar isso como uma duplicata ... bem, eu olhei mas eu estou amaldiçoado se eu pudesse descobrir como fazer isso a partir das respostas que eu li.

Alguém por favor pode me esclarecer? :)

    
por teracow 05.05.2016 / 09:49

2 respostas

2

Isso funcionará:

if [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] || [ "$bool1" == true ] ; then echo "conditions met - running code ..."; fi;

Ou rode com {;} para legível e fácil de manter no futuro.

if { [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] ;} || [ "$bool1" == true ] ; then echo "conditions met - running code ..."; fi;

Referência:

  1. Não existe variável booleana. Veja este .
  2. {;}, consulte este .
  3. & & tem maior precedência do que || = somente em (()) e [[]]

A seguir está o comprovado de & & precedência mais alta só acontece em [[]].

Assuma bool1 = verdadeiro.

[[]]:

if [[ "$bool1" == true || "$bool1" == true && "$bool1" != true ]]; then echo 7; fi #1 #print 7, due to && higher precedence than ||
if [[ "$bool1" == true ]] || { "$bool1" == true && "$bool1" != true ;}; then echo 7; fi #same like #1
if { "$bool1" == true ]] || "$bool1" == true ;} && [[ "$bool1" != true ]] ; then echo 7; fi #not same like #1

Sem [[]],

if [ "$bool1" == true ] || [ "$bool1" == true ] && [ "$bool1" != true ]; then echo 7; fi #1, no output, due to && IS NOT higher precedence than ||
if [ "$bool1" == true ] || { [ "$bool1" == true ] && [ "$bool1" != true ] ;}; then echo 7; fi #not same like #1
if { [ "$bool1" == true ] || [ "$bool1" == true ] ;} && [ "$bool1" != true ]; then echo 7; fi #same like #1
    
por 05.05.2016 / 11:33
2

O && que você está usando no final de sua expressão condicional serve para executar um comando subseqüente (seu segundo argumento) se o comando anterior (seu primeiro argumento) retornar um status de zero, que é tradicionalmente considerado um código de sucesso para programas. Além disso, o $bool1 que você colocou lá está sozinho, o que faz com que o Bash interprete seu valor como o nome de um comando ou programa a ser executado. O que você está tentando alcançar parece ser uma avaliação de expressão condicional, que é feita usando o comando if da seguinte forma: -

if [ "$string1" != "$string2" ]  && [ "$string3" != "$string4" ] || [ $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

Outra forma é usar os operadores "e", -a e "ou", -o , internos: -

if [ "$string1" != "$string2" -a "$string3" != "$string4" -o $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

Novamente, existe outra maneira que não usa o comando if: -

[[ "$string1" != "$string2" && "$string3" != "$string4" || $bool1 -ne 0 ]] && echo "conditions met - running code ..."

Observe que o valor booleano é expresso como um número inteiro, portanto, o teste de expressão inteiro para "diferente de", -ne , pode ser usado aqui. A seguir, um script que demonstra o funcionamento: -

#!/bin/bash

string1="Hello"
string2="Hello"
string3="Hello"
string4="Hello"
bool1=1

if [ "$string1" != "$string2" ]  && [ "$string3" != "$string4" ] || [ $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

exit 0
    
por 05.05.2016 / 11:07