Operadores lógicos simples en Bash

Tengo un par de variables y quiero verificar la siguiente condición (escrita en palabras, luego mi bash fallido en bash scripting):

if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then do something done. 

Y en mi bash fallido, se me ocurrió:

 if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); then scale=0.05 fi 

Lo que has escrito en realidad casi funciona (funcionaría si todas las variables fueran números), pero no es una forma idiomática en absoluto.

  • (…) paréntesis indican una subshell . Lo que hay dentro de ellos no es una expresión como en muchos otros idiomas. Es una lista de comandos (al igual que paréntesis externos). Estos comandos se ejecutan en un subproceso separado, por lo que cualquier redirección, asignación, etc. realizada dentro de los paréntesis no tiene ningún efecto fuera del paréntesis.
    • Con un signo de dólar inicial, $(…) es una sustitución de comando : hay un comando entre paréntesis, y el resultado del comando se usa como parte de la línea de comando (después de expansiones adicionales a menos que la sustitución se realice entre comillas dobles, pero esa es otra historia ).
  • { … } llaves son como paréntesis porque agrupan comandos, pero solo influyen en el análisis, no en la agrupación. El progtwig x=2; { x=4; }; echo $x x=2; { x=4; }; echo $x x=2; { x=4; }; echo $x imprime 4, mientras que x=2; (x=4); echo $x x=2; (x=4); echo $x x=2; (x=4); echo $x prints 2. (También los refuerzos requieren espacios alrededor de ellos y un punto y coma antes del cierre, mientras que los paréntesis no. Eso es solo una peculiaridad de syntax).
    • Con un signo de dólar líder, ${VAR} es una expansión de parámetros , que se expande al valor de una variable, con posibles transformaciones adicionales.
  • ((…)) paréntesis doble rodea una instrucción aritmética , es decir, un cálculo en enteros, con una syntax similar a otros lenguajes de progtwigción. Esta syntax se usa principalmente para asignaciones y en condicionales.
    • La misma syntax se usa en las expresiones aritméticas $((…)) , que se expanden al valor entero de la expresión.
  • [[ … ]] corchetes dobles rodean las expresiones condicionales . Las expresiones condicionales se basan principalmente en operadores como -n $variable para comprobar si una variable está vacía y -e $file para probar si existe un archivo. También hay operadores de igualdad de cadenas: "$string1" = "$string2" (tenga en cuenta que el lado derecho es un patrón, por ejemplo [[ $foo = a* ]] prueba si $foo comienza con a rato [[ $foo = "a*" ]] prueba si $foo es exactamente a* ), ¡y lo familiar ! , && y || operadores para negación, conjunción y disyunción, así como paréntesis para agrupar. Tenga en cuenta que necesita un espacio alrededor de cada operador (por ejemplo [[ "$x" = "$y" ]] , no [[ "$x"="$y" ]] ), y un espacio o un carácter como ; tanto dentro como fuera de los corchetes (por ejemplo, [[ -n $foo ]] , no [[-n $foo]] ).
  • [ … ] corchetes individuales son una forma alternativa de expresiones condicionales con más peculiaridades (pero más antiguas y más portátiles). No escriba ninguno por ahora; comienza a preocuparte por ellos cuando encuentres guiones que los contengan.

Esta es la forma idiomática de escribir tu prueba en bash:

 if [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]; then 

Si necesita portabilidad para otros shells, esta sería la forma (tenga en cuenta las cotizaciones adicionales y los conjuntos de corchetes por separado alrededor de cada prueba individual):

 if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then 

muy cerca

 if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]]; then scale=0.05 fi 

Deberia trabajar.

descomponiéndolo

 [[ $varA -eq 1 ]] 

es una comparación entera donde como

 $varB == 't1' 

es una comparación de cadenas. de lo contrario, solo estoy agrupando las comparaciones correctamente.

Los corchetes dobles delimitan una expresión condicional. Y, creo que lo siguiente es una buena lectura sobre el tema: “(IBM) prueba Demystify, [, [[, (y, si, entonces, otro)”

Una versión muy portátil (incluso para el shell bourne heredado):

 if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ] then do-something fi 

Esto tiene la cualidad adicional de ejecutar solo un subproceso a lo sumo (que es el proceso ‘[‘), cualquiera que sea el sabor del shell.

Reemplace “=” con “-eq” si las variables contienen valores numéricos, por ejemplo

  • 3 -eq 03 es cierto, pero
  • 3 = 03 es falso. (comparación de cadenas)
 if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ] then echo STR is empty but should have a value. fi 

Aquí está el código para la versión corta de la statement if-then-else:

 ( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok" 

Preste atención a lo siguiente:

  1. || y & operandos dentro si la condición (es decir, entre paréntesis redondos) son operandos lógicos (o / y)

  2. || y & operandos fuera si la condición significa entonces / else

Prácticamente la statement dice:

if (a = 1 o b = 2) luego “ok” else “nok”