Tengo un script de shell con bucles anidados y acabo de descubrir que "exit" realmente no sale del script, sino solo del bucle actual. ¿Hay otra forma de salir completamente del script en una determinada condición de error?
No quiero usar "set -e", porque hay errores aceptables y requeriría demasiada reescritura.
En este momento, estoy usando kill para eliminar manualmente el proceso, pero parece que debería haber una mejor manera de hacerlo.
bash -c 'for x in y z; do exit; done; echo "This never gets printed"'
.Respuestas:
Su problema no son los bucles anidados, per se. Es que uno o más de tus bucles internos se ejecutan en una subshell .
Esto funciona:
salida:
Esto presenta el problema que ha descrito:
salida:
Aquí está la solución; debe probar el valor de retorno de los bucles internos que se ejecutan en subcapas:
Tenga en cuenta la prueba:
[[ $? != 0 ]] && exit $?
salida:
Editar: para verificar en qué subshell se encuentra, modifique el script de "respuesta" para indicarle cuál es el ID de proceso de su shell actual. NOTA: Esto solo funciona en bash 4:
salida:
Las variables "i" y "j" son cortesía de Fortran. Que tengas un buen día. :-)
fuente
bash --version
en la línea de comando.Una respuesta anterior sugiere que se utilice
[[ $? != 0 ]] && exit $?
sin embargo esto no será bastante trabajo como se esperaba, debido a que la[[ $? != 0 ]]
prueba se restablecerá$?
de nuevo a cero, lo que significa que aunque el guión te con salida precoz como se esperaba, que va a salir siempre con el código 0 (no esperado) . Además, sería mejor usar la-ne
prueba de comparación numérica, en lugar de la!=
prueba de comparación de cadenas. Por lo tanto, en mi humilde opinión, una mejor solución es utilizar:ya que eso asegurará que el código de salida real esté configurado correctamente.
fuente
Puedes usar
break
.De
help break
:Entonces, para salir de tres bucles envolventes, es decir, si tiene dos bucles anidados dentro del principal, use esto para salir de todos ellos:
fuente
for((i=0;i<3;i++));do echo A;for((j=0;j<2;j++));do echo B;break 2;done;done
exit
termina todo el shell, o el sub-shell actual:fuente