Uso confuso de & & y || operadores

Estaba hojeando un archivo /etc/rc.d/init.d/sendmail (sé que casi nunca se usa, pero «m estudiando para un examen), y me he «confundido un poco acerca de los operadores && y ||. He leído dónde se pueden usar en declaraciones como:

if [ test1 ] && [ test2 ]; then echo "both tests are true" elif [ test1 ] || [ test2 ]; then echo "one test is true" fi 

Sin embargo, este script muestra declaraciones de una sola línea como:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE" [ -f /usr/sbin/sendmail ] || exit 0 

Estos parecen estar usando los operadores && y || para obtener respuestas basadas en pruebas, pero no he podido desenterrar documentación sobre este uso particular de estos operadores. ¿Alguien puede explicar qué hacen estos en este contexto en particular?

Responder

El lado derecho de && solo se evaluará si el estado de salida del lado izquierdo es cero (es decir, verdadero). || es lo contrario: evaluará el lado derecho solo si el estado de salida del lado izquierdo es distinto de cero (es decir, falso).

Puede considerar [ ... ] para ser un programa con un valor de retorno. Si la prueba interna se evalúa como verdadera, devuelve cero; devuelve distinto de cero en caso contrario.

Ejemplos:

$ false && echo howdy! $ true && echo howdy! howdy! $ true || echo howdy! $ false || echo howdy! howdy! 

Notas adicionales:

Si lo hace which [, es posible que vea que [ ¡en realidad apunta a un programa! Sin embargo, generalmente no es el que se ejecuta en los scripts; ejecute type [ para ver qué se ejecuta realmente. Si desea intentar usar el programa, simplemente proporcione la ruta completa como entonces: /bin/[ 1 = 1.

Comentarios

  • Cuando vea » X o Y «, prueba X. Si ‘ es verdadero, ya conoce la respuesta a » X o Y » (es ‘ cierto), por lo que no es necesario probar Y. Si ‘ s cierto, no ‘ no conoces la respuesta a » X o Y «, por lo que debe probar Y. Cuando vea » X e Y » , prueba X. Si ‘ es falso, ya conoce la respuesta a » X e Y » (es ‘ s falso), s o no es necesario probar Y. Si X es verdadera, entonces debe probar Y para ver si » X e Y » son verdadero.
  • En lugar de » si el lado izquierdo devuelve cero «, escribiría » si el estado de salida del comando del lado izquierdo ‘ es cero «. Encuentro » return » un poco ambiguo ya que la salida y el estado de salida pueden considerarse como » valores de retorno »
  • No solo puede » considerar [ ... ] para ser un programa «, en muchos casos es . Suele estar ‘ en el archivo /bin/[ o /usr/bin/[.
  • Los programadores de C encontrarán esto muy confuso. Hay 0 significa falso … Mientras que en shellscripting 0 significa verdadero … Alucinante.
  • @Calmarius Si ‘ estás acostumbrado a C, piensa en return estados, no booleanos, donde return 0 significa éxito.

Respuesta

Aquí está mi hoja de trucos:

  • «A; B «Ejecute A y luego B, independientemente del éxito de A
  • » A & & B «Ejecute B si A tuvo éxito
  • «A || B «Ejecute B si A falló
  • » A & «Ejecute A en segundo plano.

Comentarios

  • Hay ‘ s algunos paralelos interesantes de cálculo lambda que están sucediendo aquí, demostrados en JavaScript funcional (defina las variables en orden); » izquierda (también conocida como verdadero) «: (a => b => a). » correcto (también conocido como falso) «: (a => b => b). » A; B » » luego » (a => b => (() => b())(a())). » A & & B » » si no tiene más (cuando) » (a => b => a()(() => right)(b)).» A || B » » más sin if (a menos que) » (a => b => a()(b)(() => right)). » a & & b || c » » ifThenElse » (a => b => c => (unless(when(a)(b))(c))()) .
  • tenga en cuenta que en bash, la izquierda es análoga 0 / cadena vacía, la derecha análoga es todo lo demás.
  • ¿Qué pasa con una sola barra vertical?

Respuesta

para expandir la respuesta de @ Shawn-j-Goff de arriba, && es un Y lógico, y || es un O lógico.

Consulte esta parte de la Advanced Bash Scripting Guide. Algunos de los contenidos del enlace para referencia del usuario se muestran a continuación.

& & Y

if [ $condition1 ] && [ $condition2 ] # Same as: if [ $condition1 -a $condition2 ] # Returns true if both condition1 and condition2 hold true... if [[ $condition1 && $condition2 ]] # Also works. # Note that && operator not permitted inside brackets #+ of [ ... ] construct. 

|| O

if [ $condition1 ] || [ $condition2 ] # Same as: if [ $condition1 -o $condition2 ] # Returns true if either condition1 or condition2 holds true... if [[ $condition1 || $condition2 ]] # Also works. # Note that || operator not permitted inside brackets #+ of a [ ... ] construct. 

Responder

Según mi experiencia, utilizo & & un d || para reducir una declaración if a una sola línea.

Digamos que estamos buscando un archivo llamado /root/Sample.txt, entonces la iteración tradicional sería la siguiente en shell:

if [ -f /root/Sample.txt ] then echo "file found" else echo "file not found" fi 

Estas 6 líneas se pueden reducir a una sola línea:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found" 

Al ejecutar algunas iteraciones para establecer variables o para crear archivos, etc., la vida es más fácil y el script se ve más elegante usando la función if de una sola línea, su único inconveniente es que se vuelve un poco más difícil implementar múltiples comandos de una sola iteración, sin embargo, puede hacer uso de funciones.

Comentarios

  • Esto es genial. Me recuerda al código objc (a == b)? val = 1: val = 2;
  • ¿Cómo puedo usar este comando cuando quiero ejecutar un proceso en segundo plano con » & «? Aparece un error de sintaxis para ./someScript.sh & && echo 'ok' || echo 'ko'
  • En el formato: foo && bar || baz, si foo tiene éxito, luego bar falla, baz se ejecutará, por lo que es sutilmente diferente de un if.
  • Debo notar que es posible ejecutar varios comandos en una fila en {} paréntesis, usando && o ||, como: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. También vale la pena mencionar que if..then..else es un » reconocedor » más confiable de true / condiciones falsas que usar && y ||.

Respuesta

Existe una noción de «atajo».

Cuando se evalúa (expr1 && expr2)expr2 solo se evalúa si exp1 se evalúa como» verdadero «. Esto se debe a que tanto expr1 Y expr2 tienen que ser verdaderos para que (expr1 && expr2) sea verdadero. Si expr1 se evalúa como «falso» expr2 NO se evalúa (atajo) porque (expr1 && expr2) ya es «flase».

Intente lo siguiente: suponga que el archivo F1 existe & archivo F2 no existe:

( [ -s F1 ] && echo "File Exists" ) # will print "File Exists" - no short cut ( [ -s F2 ] && echo "File Exists" ) # will NOT print "File Exists" - short cut

De manera similar para || (o) – pero breve el corte se invierte.

Comentarios

  • La lógica generalmente se denomina » cortocircuito «. ‘ nunca he visto la frase » abreviatura » utilizada. Menciono esto para ayudar a encontrar referencias.

Respuesta

Los ejemplos en la respuesta de Shawn J. Goff son correctos, pero la explicación es al revés. Compruebe:

El lado derecho de & & sólo se evaluará si el estado de salida del lado izquierdo es NONZERO. || es lo contrario: evaluará el lado derecho solo si el estado de salida del lado izquierdo es CERO.

Comentarios

  • Sabe que para los shells el código de salida cero se evalúa como verdadero y, por lo tanto, el código de salida distinto de cero en el lado izquierdo de && da como resultado que toda la expresión devuelva false ?
  • Alguien no aprobó sus ediciones porque no era su respuesta.Si cree que alguna respuesta es incorrecta, debe rechazarla y posiblemente dejar un comentario; si cree que requiere un cambio, debe dejar un comentario. La edición sirve para corregir errores gramaticales, de formato y ortografía que no cambian el significado de la respuesta.
  • @countermode I ‘ lo siento, tienes razón, Pensé en Linux zero = false y nonzero = true (como en C y muchos otros lenguajes / entornos / plataformas). Pido disculpas por el malentendido.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *