Considera los comandos
eval false || echo ok
echo also ok
Normalmente, esperaríamos que esto ejecute la false
utilidad y, dado que el estado de salida es distinto de cero, luego ejecutar echo ok
y echo also ok
.
En todo el POSIX como conchas que utilizo ( ksh93
, zsh
, bash
, dash
, OpenBSD ksh
, y yash
), esto es lo que sucede, pero las cosas se ponen interesantes si permitimos set -e
.
Si set -e
está vigente, OpenBSD sh
y ksh
shells (ambos derivados de pdksh
) terminarán el script al ejecutar el eval
. Ningún otro caparazón hace eso.
POSIX dice que un error en una utilidad incorporada especial (como eval
) debería hacer que el shell no interactivo finalice. No estoy completamente seguro de si la ejecución false
constituye "un error" (si lo fuera, sería independiente de set -e
estar activo).
La forma de evitar esto parece ser poner eval
un sub shell,
( eval false ) || echo ok
echo also ok
La pregunta es si se espera que tenga que hacer eso en un script de shell POSIX-ly correcto, o si es un error en el shell de OpenBSD. Además, ¿qué se entiende por "error" en el texto POSIX vinculado anteriormente?
Información adicional: los shells de OpenBSD ejecutarán echo ok
ambos con y sin set -e
el comando
eval ! true || echo ok
Mi código original parecía
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
lo que no la salida not ok
con string=false
el uso de las conchas de OpenBSD (sería terminar), y no estaba seguro de que era por diseño, por error o por mala interpretación, o alguna otra cosa.
eval false
genera un estado distinto de cero, por lo que esperaríaset -e
terminar el script en ese punto. En el caso de!
set -e
no se aplica, ya que la!
declaración verifica explícitamente el estado de salida.eval false
terminar el script incluso si es parte de una lista AND-OR o una declaración condicional? Yo no lo haríaset -e
se establece si ese es el comportamiento correcto ... Estoy de acuerdo en que tiene sentido no terminar en una declaración condicional.set -e
por lo que `()` es la respuesta.Respuestas:
Que ningún otro shell necesite tal solución alternativa es una fuerte indicación de que es un error en OpenBSD ksh. De hecho, ksh93 no muestra ese problema.
Que haya un
||
en la línea de comando debe evitar la salida del shell causada por un código de retorno de 1 en el lado izquierdo.El error de una función incorporada especial provocará la salida de un shell no interactivo según POSIX, pero eso no siempre es cierto. Intentar
continue
salir de un bucle es un error, ycontinue
está integrado. Pero la mayoría de los proyectiles no salen:Una construcción que emite un error claro pero no sale.
Entonces, la salida activada
false
se genera por laset -e
condición, no por la característica incorporada del comando (eval
en este caso).Las condiciones exactas en las que
set -e
debe salir son bastante más difusas en POSIX.fuente
[perdón si esta no es una respuesta real, la actualizaré cuando llegue el momento]
Eché un vistazo al código fuente y mis conclusiones son:
1) Es un error / limitación, nada filosófico detrás de esto.
2) La "solución" de la bifurcación portátil de ksh (
mksh
) de OpenBSD es muy pobre, solo empeora las cosas, sin realmente arreglarlo:Nuevo error, diferente de todos los otros shells:
Todavía no está realmente solucionado:
Puede reemplazar
bash
anterior condash
,zsh
,yash
,ksh93
, etc.fuente