Pregunta:
Estoy trabajando con Bash 3 y estoy tratando de formar un condicional. En C / C ++, es absolutamente simple: ((A || B) && C)
. En Bash, no es así (creo que los autores de Git deben haber contribuido con este código antes de pasar a otros esfuerzos).
Esto no funciona. Tenga en cuenta que <0 or 1>
no es una cadena literal; significa un 0 o 1 (generalmente proviene de grep -i
).
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi
En resultado de:
line 322: syntax error near unexpected token `[['
Luego intenté:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi
en resultado de:
line 322: syntax error near unexpected token `[['
Parte del problema es que los resultados de la búsqueda son ejemplos triviales y no ejemplos más complejos con condicionales compuestos.
¿Cómo realizo un simple ((A || B) && C)
en Bash?
Estoy listo para desenrollarlo y repetir los mismos comandos en varios bloques:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then
...
elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then
...
fi
Respuesta:
La sintaxis de bash no es similar a C, incluso si una pequeña parte está inspirada en C. No puedes simplemente intentar escribir código C y esperar que funcione.
El objetivo principal de un shell es ejecutar comandos. El comando de corchete abierto [
es un comando que realiza una sola prueba¹. Incluso puede escribirlo como test
(sin el corchete de cierre final). El ||
y los operadores &&
son operadores de shell, combinan comandos , no pruebas.
Entonces cuando escribes
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]
eso es analizado como
[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]
que es lo mismo que
test [ "$A" -eq "0" ||
test "$B" -ne "0" ] &&
test "$C" -eq "0"
¿Observa los corchetes desequilibrados? Sí, eso no es bueno. Su intento con paréntesis tiene el mismo problema: corchetes falsos.
La sintaxis para agrupar comandos es llaves. La forma en que se analizan las llaves requiere un comando completo antes que ellas, por lo que deberá terminar el comando dentro de las llaves con una nueva línea o punto y coma.
if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then …
Existe una forma alternativa que consiste en utilizar corchetes dobles. A diferencia de los corchetes simples, los corchetes dobles son una sintaxis de shell especial. Delimitan expresiones condicionales . Dentro de los corchetes dobles, puede utilizar paréntesis y operadores como &&
y ||
. Dado que los corchetes dobles son sintaxis de shell, el shell sabe que cuando estos operadores están entre corchetes, son parte de la sintaxis de expresión condicional, no parte de la sintaxis de comandos de shell ordinaria.
if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …
Si todas sus pruebas son numéricas, existe otra forma, que delimita las expresiones artihméticas . Las expresiones aritméticas realizan cálculos de números enteros con una sintaxis muy similar a la de C.
if (((A == 0 || B != 0) && C == 0)); then …
Puede encontrar útil mi manual básico de corchetes bash .
[
se puede utilizar en sh. [[
y ((
son específicos de bash (y ksh y zsh).
¹ También puede combinar múltiples pruebas con operadores booleanos, pero esto es engorroso de usar y tiene trampas sutiles, así que no lo explicaré.