Para estar seguro, me gustaría que bash aborte la ejecución de un script si encuentra un error de sintaxis.
Para mi sorpresa, no puedo lograr esto. ( set -e
no es suficiente) Ejemplo:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado (bash-3.2.39 o bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Bueno, no podemos verificar $?
después de cada declaración para detectar errores de sintaxis.
(Esperaba un comportamiento tan seguro de un lenguaje de programación sensible ... tal vez esto debe ser reportado como un error / deseo de criticar a los desarrolladores)
Más experimentos
if
No hace diferencia.
Removiendo if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Quizás, está relacionado con el ejercicio 2 de http://mywiki.wooledge.org/BashFAQ/105 y tiene algo que ver (( ))
. Pero todavía me parece irrazonable continuar ejecutando después de un error de sintaxis.
No, (( ))
no hay diferencia!
¡Se comporta mal incluso sin la prueba aritmética! Solo un script simple y básico:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Resultado:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
fuente
set -e
no es suficiente porque su error de sintaxis está en unaif
declaración. En cualquier otro lugar debería abortar el script.set -e
no ha funcionado. Pero mi pregunta aún tiene sentido. ¿Es posible abortar en cualquier error de sintaxis?Respuestas:
Ajustar el todo en una función parece hacer el truco:
Resultado:
Aunque no tengo idea de por qué, ¿tal vez alguien más pueda explicarlo?
fuente
echo 'Bad2: has not aborted the execution after bad main!'
como último a su ejemplo, y el resultado es: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: línea 6: #: error de sintaxis: operando esperado ( el token de error es "#") Malo2: ¡no ha abortado la ejecución después de un mal principal! $Probablemente esté engañando sobre el significado genuino de
set -e
. Una lectura cuidadosa de la salida dehelp set
espectáculos:Entonces,
-e
se trata del estado de salida de los comandos que no son cero, no de los errores de sintaxis en su script.En general, se considera una mala práctica usar
set -e
, porque todos los errores (es decir, todos los retornos distintos de cero de los comandos) deben ser manejados de manera inteligente por el script (piense en un script robusto, no los que se vuelven locos después de ingresar un nombre de archivo con un espacio o que comienza con una exageración).Dependiendo del tipo de error de sintaxis, es posible que el script ni siquiera se ejecute. No tengo suficiente conocimiento en bash para decir exactamente qué clase de errores de sintaxis (si solo se pueden clasificar) podría conducir a un aborto inmediato del script o no. Quizás algunos gurús de Bash se unan y aclaren todo.
¡Solo espero haber aclarado la
set -e
declaración!Sobre su deseo:
La respuesta es definitivamente no! ya que lo que has observado (
set -e
sin responder como esperas) está de hecho muy bien documentado.fuente
set -e
, está un poco cerca de mis objetivos, es por eso que se menciona y se usa aquí. Mi pregunta noset -e
es acerca de la inseguridad de bash si no se puede abortar en errores de sintaxis. Estoy buscando una manera de hacerlo siempre abortar en errores de sintaxis.Puede hacer que el script se verifique por sí mismo poniendo algo como
cerca de la parte superior de la secuencia de comandos, después
set -e
pero antes de cualquier fragmento de código significativo.Debo decir que esto no se siente muy robusto, pero si funciona para usted, tal vez sea aceptable.
fuente
set -e
:bash -n "$0" || exit
Primero el
(( ))
in bash se usa como cálculos aritméticos, no para usar en el if ... use the[]
para eso.En segundo lugar, el
${a[#]}
es extraño y es por eso que está dando errores ...#
no tiene ningún significado de matrizNo sé qué quieres hacer con esto, pero supongo que quieres saber la cantidad de campos, así que quieres
${#a[*]}
en su lugarFinalmente, cuando se comparan enteros,
-eq
se recomienda sobre==
(usado para cadenas). el==
también funcionará, pero-eq
se recomienda.Entonces quieres:
fuente
((
palabra clave con laif
palabra clave. Por ejemplo,if (( 5 * $b > 53 ))
. A menos que esté buscando la portabilidad con proyectiles más antiguos, generalmente[[
es preferible hacerlo[
.[[
y((
fueron diseñados específicamente como pruebas livianas para usar con "si", etc., a diferencia de esto[
, nunca generan un subproceso para evaluar la condición.[
es un bash incorporado. Sin embargo, los proyectiles más antiguos esperan que sea su propio programa.