¿Cuál es la diferencia entre usar:
eval "echo "foo""
y
echo "echo "foo"" | bash
¿hay alguno?
Comentarios
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, perox=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.
( eval 'echo "foo"' )