Comportamiento de "eval" bajo "set -e" en expresión condicional

Comportamiento de "eval" bajo "set -e" en expresión condicional

Considere los comandos

eval false || echo ok
echo also ok

Normalmente, esperaríamos que esto ejecutara la falseutilidad y, dado que el estado de salida es distinto de cero, luego ejecutaría echo oky echo also ok.

En todos los shells tipo POSIX que uso ( ksh93,,, OpenBSD y ), esto es lo que sucede, pero las cosas se ponen interesantes si habilitamos .zshbashdashkshyashset -e

Si set -eestá vigente, OpenBSD shy kshshells (ambos derivados de pdksh) finalizarán el script al ejecutar eval. Ningún otro caparazón hace eso.

POSIX diceque un error en una utilidad especial incorporada (como eval) debería provocar la finalización del shell no interactivo. No estoy del todo seguro de si la ejecución falseconstituye "un error" (si lo fuera, sería independiente de set -eestar activo).

La forma de solucionar esto parece ser colocarlo evalen un subshell,

( eval false ) || echo ok
echo also ok

La pregunta es si se espera que tenga que hacer eso en un script de shell POSIX correcto o si se trata de un error en el shell de OpenBSD. Además, ¿qué se entiende por "error" en el texto POSIX vinculado anteriormente?


Un poco de información adicional: los shells de OpenBSD ejecutarán echo oktanto con como sin set -e en 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

Cuál deberíanosalida not okcon string=falseel uso de shells de OpenBSD (terminaría), y no estaba seguro de que fuera por diseño, por error o por malentendido, o algo más.

Respuesta1

El hecho de que ningún otro shell necesite dicha solución es un fuerte indicio de que se trata de 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 provocada por un código de retorno de 1 en el lado izquierdo del mismo.

El error de unespecialincorporado provocará la salida de un shell no interactivosegún POSIXpero eso no siempre es cierto. Intentar continuesalir de un bucle es un error y continuees una función incorporada. Pero la mayoría de los shells no salen en:

continue 3

Un incorporado que emite un error claro pero no sale.

Entonces, la salida falsees generada por la set -econdición, no por la característica incorporada del comando ( evalen este caso).

Las condiciones exactas sobre las cuales set -ese saldrá son bastante más confusas en POSIX.

Respuesta2

[lo siento 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, no hay nada filosófico detrás de esto.

mksh2) La "solución" de la bifurcación portátil de ksh ( ) de OpenBSD esmuypobre, sólo empeora las cosas, sin realmente arreglarlas:

Nuevo error, diferente de todos los demás shells:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

Todavía no está realmente solucionado:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

Puede reemplazar bashlo anterior con dash, zsh, yash, ksh93etc.

información relacionada