eval vs. pipe a través de bash

¿Cuál es la diferencia entre usar:

eval "echo "foo"" 

y

echo "echo "foo"" | bash 

¿hay alguno?

Comentarios

  • Aquí ' hay otra variación con un comportamiento ligeramente diferente en cuanto a entornos de ejecución: ( eval 'echo "foo"' )

Respuesta

Respuesta corta

El comando ejecutado por eval se ejecuta en el shell actual y el comando canalizado a bash se ejecuta en un sub-shell, por ejemplo:

> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42 

Respuesta más larga

En los comentarios se afirmó que en versiones más recientes de bash (> = 4.2) el primer comando también podría tener el mismo efecto. Sin embargo, este no parece ser el caso.

En realidad, hay un par de factores que hacen que el comando canalizado no se ejecute en la sesión actual: el canal y el bash.

En su mayor parte, los comandos canalizados se ejecutan en subcapas. El Manual de Bash ( Sección 3.2.2: Pipelines ) tiene lo siguiente para decir:

Cada comando de una canalización se ejecuta en su propia subcapa (consulte Entorno de ejecución de comandos ).

Como se señaló en los comentarios, este comportamiento se puede modificar mediante la opción lastpipe. El Manual de Bash ( Sección 4.3.2: The Shopt Builtin ) tiene lo siguiente que decir sobre la opción lastpipe:

lastpipe

Si se establece, y el control del trabajo no está activo, el shell ejecuta el último comando de una tubería no ejecutada en el background en el entorno de shell actual.

Podemos verificar que este es el caso de la siguiente manera.

Primero habilite lastpipe:

> shopt -s lastpipe 

Luego, inhabilite el control de trabajo:

> set +m 

Ahora ejecute un comando que establezca una variable desde dentro de una tubería:

> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42 

Observe que usamos el while loop y el comando read como solución alternativa, ya que el comando eval no puede leer su entrada desde stdin (por lo tanto, no puede obtener su entrada de una tubería).

Este ejemplo demuestra que el comando más a la derecha en la tubería puede, de hecho , se ejecutará en el shell actual. Sin embargo, esto en realidad no afecta nuestro ejemplo original. Incluso con lastpipe habilitado y el control de trabajo deshabilitado, seguimos obteniendo el siguiente resultado al conectar a bash:

> echo "x=42" | bash; echo $x > 

Esto se debe a que el comando bash en sí mismo ejecuta su entrada en una subshell.

Comentarios

  • esa es una buena observación, no ' no me di cuenta de eso, pero sí, supongo que ' s cómo funcionan las tuberías
  • Solo por curiosidad, ¿cuál es la razón por la que no aceptó la respuesta?
  • Para bash 4.2+ cuando se ejecuta un script (o más exactamente cuando jobcontrol está desactivado) y shopt lastpipe está configurado y la canalización no está en segundo plano, se ejecuta en el extremo derecho de la canalización en la ' superior ' shell no es un subshell. Consulte unix.stackexchange.com/questions/9954/… y unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 El comando bash se puede ejecutar en la capa superior dependiendo de las opciones, pero x=42 seguramente se ejecutará en algo que razonablemente se puede llamar una subcapa.
  • @AlexanderMills En realidad, la tubería no es ' t es el único problema. El comando bash ejecutará su entrada en una subcapa independientemente de si hay una tubería o no involucrada. Consulte la actualización de mi solución para obtener más detalles.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *