Bash si la declaración con múltiples condiciones arroja un error

165

Estoy tratando de escribir un script que verificará dos marcas de error, y en caso de que se cambie una bandera (o ambas), hará eco: se produjo un error. Mi guión:

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

Básicamente, debería ser, algo junto:

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

El error que obtengo es:

 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'

¿Están arruinados mis soportes?

Simplemente yo
fuente
2
Use paréntesis - ()
AlikElzin-kilaka
3
Lógicamente, a==1 or b==2ya cubre el caso donde a==1 and b==2. Probar por separado para eso es completamente superfluo aquí.
tripleee

Respuestas:

249

Utilice -a(para y) y -o(para o) operaciones.

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

Actualizar

En realidad, aún podría usar &&y ||con la -eqoperación. Entonces su guión sería así:

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

Aunque en su caso puede descartar las dos últimas expresiones y simplemente seguir con una u operación 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
fuente
3
@Simply_Me: No, un OR lógico es verdadero si uno o ambos de sus operandos son verdaderos. Estás pensando en "exclusivo o" (XOR), lo cual es cierto si exactamente uno de sus operandos es verdadero. (En realidad, hay versiones de XOR que funcionan en más de 2 operandos, en cuyo caso es cierto si es cierto un número impar de operandos).
Gordon Davisson
44
Por cierto, los problemas en el código original incluyen el uso [y ]para la agrupación (no lo hacen), y no poner espacios alrededor del operador (por ejemplo "$my_error_flag"="1"), lo que impide que el shell lo reconozca como un operador. Lea BashFAQ # 17 (sobre agrupación) y # 31 (sobre la diferencia entre los diferentes tipos de expresión de prueba) . En realidad, en este caso sería aún más fácil usar una expresión aritmética .
Gordon Davisson el
77
-ay -ose consideran obsoletos por la especificación POSIX ; use pruebas separadas combinadas con las ||de la actualización.
chepner
1
No es necesario agrupar usando subcapas, normalmente {}también debería ser posible agrupar usando .
phk
1
para agregar al comentario anterior de phk, () está lanzando subshells en bash, que pueden tener todo tipo de efectos sutiles [probablemente no deseados].
brett
70

Puede usar cualquiera [[o ((palabra clave. Cuando se utiliza [[la palabra clave, usted tiene a los operadores el uso de cadenas, tales como -eq, -lt. Creo que ((es el más preferido para la aritmética, porque puedes usar operadores directamente como ==, <y >.

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

No utilice -ani -ooperadores ya que no es portátil.

Fizer Khan
fuente
8

Por favor intente 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
fuente
2
( ... )crea subcapas: un gran impacto en el rendimiento sin ningún beneficio.
Charles Duffy
44
Úselo { ...; }para agrupar sin creación de subshell.
Charles Duffy
1

Puede obtener algo de inspiración leyendo un entrypoint.sh script escrito por los contribuyentes de MySQL que verifica si se establecieron las variables especificadas.

Como muestra el script, puede canalizarlos -a, por ejemplo:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi
Daniel Andrei Mincă
fuente
1
-aestá marcado como obsoleto en la versión actual del testestándar POSIX ; vea los OBmarcadores en pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Use [ -z "$FOO" ] && [ -z "$BAR" ]para tener un código más confiable.
Charles Duffy