Estoy aprendiendo sobre las estructuras de toma de decisiones y me encontré con estos códigos:
if [ -f ./myfile ]
then
cat ./myfile
else
cat /home/user/myfile
fi
[ -f ./myfile ] &&
cat ./myfile ||
cat /home/user/myfile
Ambos se comportan igual. ¿Hay alguna ventaja en usar una forma de la otra?
shell-script
syntax
control-flow
Subhaa Chandar
fuente
fuente

Respuestas:
No, construcciones
if A; then B; else C; fiy noA && B || Cson equivalentes .Con
if A; then B; else C; fi, el comandoAsiempre se evalúa y ejecuta (al menos se intenta ejecutarlo) y luego se evalúa y ejecuta el comandoBo el comandoC.Con
A && B || C, que es la misma para los comandosAyBpero diferente paraC: comandoCse evalúa y ejecuta si bienAfalla oBfalla.En su ejemplo, suponga que
chmod u-r ./myfile, entonces, a pesar de tener[ -f ./myfile ]éxito, lo harácat /home/user/myfileMi consejo: use
A && BoA || Btodo lo que quiera, esto sigue siendo fácil de leer y comprender y no hay trampa. Pero si te refieres a si ... entonces ... más ... entonces úsaloif A; then B; else C; fi.fuente
A la mayoría de las personas les resulta más fácil comprender la
if...then...else...fiforma.Para el
a && b || c, debe asegurarse de quebdevuelve verdadero. Esta es una causa de errores sutiles y es una buena razón para evitar este estilo. Si b no devuelve verdadero, estos no son lo mismo.Para pruebas y acciones muy cortas que no tienen una cláusula else, la longitud acortada es atractiva, p. Ej.
&&y||sonshort circuiting operators, tan pronto como se conozca el resultado de otras pruebas que no sean necesarios se pasan por alto.a && b || cse agrupa como(a && b) || c. Primeroase corre. Si sefailsdefine como que no devuelve un estado de salida de 0, entonces el grupo(a && b)es conocidofailybno necesita ejecutarse. El||no sabe el resultado de la expresión, por lo que debe ejecutarsec. Siatiene éxito (devuelve cero), el&&operador aún no sabe el resultado dea && blo que tiene que correrbpara averiguarlo. Sibtiene éxito, entoncesa && btiene éxito y||sabe que el resultado general es exitoso, por lo que no necesita ejecutarsec. Sibfalla entonces||aún no conoce el valor de la expresión, por lo que debe ejecutarsec.fuente
El operador && ejecuta el siguiente comando si el comando anterior tuvo una ejecución exitosa (código de salida devuelto ($?) 0 = lógico verdadero).
En el formulario
A && B || C, se evalúa el comando (o condición) A y si A devuelve verdadero (éxito, código de salida 0), se ejecuta el comando B. Si A falla (por lo tanto devolverá falso - el código de salida es diferente a 0) y / o B falla (devolver falso ), entonces se ejecutará el comando C.También el
&&operador se utiliza como AND en las comprobaciones de condición y el operador||funciona como OR en las comprobaciones de condición.Dependiendo de lo que desee hacer con su script, el formulario
A && B || Cpuede usarse para verificaciones de condición como su ejemplo o puede usarse para encadenar comandos y garantizar una serie de comandos que se ejecutarán si los comandos anteriores tuvieron un código de salida 0 exitoso .Por esta razón, es común ver comandos como:
do_something && do_something_else_that_depended_on_something.Ejemplos:
apt-get update && apt-get upgradesi la actualización falla, la actualización no se ejecuta (tiene sentido en el mundo real ...).mkdir test && echo "Something" > test/fileLa parte
echo "Something"se ejecutará solo simkdir testfue exitosa y la operación devolvió el código de salida 0 ../configure --prefix=/usr && make && sudo make installGeneralmente se encuentra en la compilación de trabajos para encadenar los comandos dependientes necesarios.
Si intenta implementar "cadenas" anteriores con if , entonces , de lo contrario , necesitará muchos más comandos y comprobaciones (y, por lo tanto, más código para escribir, más cosas que saldrán mal) para una tarea simple.
Además, tenga en cuenta que los comandos encadenados con && y || son leídos por shell de izquierda a derecha. Es posible que deba agrupar comandos y verificaciones de condición con corchetes para depender del siguiente paso en la salida exitosa de algunos comandos anteriores. Por ejemplo, mira esto:
O un ejemplo de la vida real:
Tenga en cuenta que algunos comandos devuelven diferentes códigos de salida según el proceso ejecutado, o devuelven diferentes códigos según sus acciones (por ejemplo, el comando GNU
diff, devuelve 1 si dos archivos difieren y 0 si no lo hacen). Dichos comandos deben tratarse con cuidado en && y || .También solo para tener todo el rompecabezas juntos, tenga en cuenta la concatenación de comandos utilizando el
;operador. Con un formato,A;B;Ctodos los comandos se ejecutarán en serie sin importar cuál fue el código de comando de salidaAyB.fuente
Gran parte de la confusión sobre esto puede deberse a la documentación de bash que llama a estas listas AND y OR . Si bien son lógicamente similares al
&&y se||encuentran dentro de los corchetes, funcionan de manera diferente.Algunos ejemplos pueden ilustrar esto mejor ...
Si
cmdasale verdadero,cmdbse ejecuta.Si
cmdasale falso,cmdbNO se ejecuta, perocmdces.Cómo
cmdase ignora las salidas.Si
cmdbsale verdadero,cmdcse ejecuta.Si
cmdbsale falso,cmdcNO se ejecuta ycmddes.Si
cmdasale verdadero,cmdbse ejecuta, seguido decmdc.Si
cmdasale falso,cmdbNO se ejecuta perocmdces.¿Eh? ¿Por qué se
cmdcejecuta?Porque para el intérprete, un punto y coma (
;) y una nueva línea significan exactamente lo mismo. Bash ve esa línea de código como ...Para lograr lo que se espera, debemos encerrar
cmdb; cmdcdentro de llaves para convertirlas en un Compound Command (comando de grupo) . El punto y coma de terminación adicional es solo un requisito de la{ ...; }sintaxis. Entonces tenemos ...cmda && { cmdb; cmdc; }Si
cmdasale verdadero,cmdbse ejecuta, seguido decmdc.Si
cmdasale falso, ningunocmdbocmdcse ejecuta.La ejecución continúa con la siguiente línea.
Uso
Las listas de comandos condicionales son más útiles para regresar tan pronto como sea posible de las funciones y así evitar interpretar y ejecutar un montón de código innecesario. Sin embargo, los retornos de funciones múltiples significan que uno debe ser obsesivo acerca de mantener las funciones cortas para que sea más fácil asegurarse de que todas las condiciones posibles estén cubiertas.
Aquí hay un ejemplo de un código en ejecución ...
fuente