Estoy tratando de entender cómo funciona la precedencia del operador lógico en bash. Por ejemplo, hubiera esperado que el siguiente comando no hiciera eco de nada.
true || echo aaa && echo bbb
Sin embargo, contrariamente a mis expectativas, bbb
se imprime.
¿Puede alguien explicarme, cómo puedo entender el &&
compuesto? y ||
operadores en bash?
Respuesta aceptada:
En muchos lenguajes de programación, los operadores con la misma precedencia son asociativos por la izquierda. Es decir, en ausencia de estructuras de agrupación, las operaciones más a la izquierda se ejecutan primero. Bash no es una excepción a esta regla.
Esto es importante porque, en Bash, &&
y ||
tienen la misma precedencia.
Entonces, lo que sucede en su ejemplo es que la operación más a la izquierda (||
) se lleva a cabo primero:
true || echo aaa
Dado que true
es obviamente cierto, el ||
cortocircuitos del operador y toda la afirmación se considera verdadera sin necesidad de evaluar echo aaa
como era de esperar. Ahora queda hacer la operación más a la derecha:
(...) && echo bbb
Dado que la primera operación se evaluó como verdadera (es decir, tuvo un estado de salida de 0), es como si estuviera ejecutando
true && echo bbb
entonces el &&
no provocará un cortocircuito, por lo que verá bbb
repitió.
Obtendrías el mismo comportamiento con
false && echo aaa || echo bbb
Notas basadas en los comentarios
- Debe tener en cuenta que la regla de asociatividad por la izquierda es solo seguido cuando ambos operadores tienen lo mismo precedencia. Este no es el caso cuando usa estos operadores junto con palabras clave como
[[...]]
o((...))
o usa el-o
y-a
operadores como argumentos paratest
o[
comandos En tales casos, AND (&&
o-a
) tiene prioridad sobre OR (||
o-o
). Gracias al comentario de Stephane Chazelas por aclarar este punto. -
Parece que en C y lenguajes similares a C
&&
tiene mayor precedencia que||
probablemente por eso esperaba que su construcción original se comportara comotrue || (echo aaa && echo bbb).
Sin embargo, este no es el caso con Bash, en el que ambos operadores tienen la misma precedencia, razón por la cual Bash analiza su expresión utilizando la regla de asociatividad izquierda. Gracias al comentario de Kevin por mencionar esto.
-
También puede haber casos en los que los 3 se evalúan las expresiones. Si el primer comando devuelve un estado de salida distinto de cero, el
||
no se cortocircuitará y continúa ejecutando el segundo comando. Si el segundo comando regresa con un estado de salida cero, entonces&&
no se cortocircuitará también y se ejecutará el tercer comando. Gracias al comentario de Ignacio Vázquez-Abrams por mencionar esto.