Quelle est la différence entre utiliser:
eval "echo "foo""
et
echo "echo "foo"" | bash
y en a-t-il?
Commentaires
Réponse
Réponse courte
La commande exécutée par eval
est exécutée dans le shell courant et la commande redirigée vers bash
est exécutée dans un sous-shell, par exemple:
> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42
Réponse plus longue
Dans les commentaires, il a été affirmé que dans les versions plus récentes de bash
(> = 4.2) la première commande pourrait également avoir le même effet. Cependant, cela ne semble pas être le cas.
Il y a en fait quelques facteurs qui empêchent la commande piped de sexécuter dans la session en cours: le tube et le bash
.
Pour la plupart, les commandes piped sexécutent dans des sous-shell. Le manuel Bash ( Section 3.2.2: Pipelines ) indique ce qui suit:
Chaque commande dun pipeline est exécutée dans son propre sous-shell (voir Environnement dexécution des commandes ).
Comme indiqué dans les commentaires, ce comportement peut être modifié via loption lastpipe
. Le manuel Bash ( Section 4.3.2: The Shopt Builtin ) a ce qui suit à propos de loption lastpipe
:
lastpipe
Sil est défini et que le contrôle des travaux nest pas actif, le shell exécute la dernière commande dun pipeline non exécuté dans le background dans lenvironnement shell actuel.
Nous pouvons vérifier que cest le cas comme suit.
Commencez par activer lastpipe
:
> shopt -s lastpipe
Ensuite, désactivez le contrôle des tâches:
> set +m
Maintenant, exécutez une commande qui définit une variable depuis un tube:
> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42
Notez que nous utilisons le while
loop et la commande read
comme solution de contournement car la commande eval
ne peut pas lire son entrée depuis stdin (par conséquent, elle ne peut pas obtenir son entrée depuis un tube).
Cet exemple montre que la commande la plus à droite du tube peut, en fait , être exécuté dans le shell actuel. Cependant, cela naffecte pas réellement notre exemple original. Même avec lastpipe
activé et le contrôle des tâches désactivé, nous obtenons toujours le résultat suivant lors de la canalisation vers bash
:
> echo "x=42" | bash; echo $x >
Ceci est dû au fait que la commande bash
exécute elle-même son entrée dans un sous-shell.
Commentaires
- cest une bonne observation, ' je ne men suis pas rendu compte, mais oui, je suppose que ' s comment fonctionnent les tuyaux
- Juste curieux, quelle est la raison pour laquelle vous navez pas accepté la réponse?
- Pour bash 4.2+ lors de lexécution dun script (ou plus exactement lorsque le contrôle des tâches est désactivé) et shopt
lastpipe
est défini et le pipeline nest pas en arrière-plan, il exécute lextrémité droite du tube dans le ' haut ' shell nest pas un sous-shell. Voir unix.stackexchange.com/questions/9954/… et unix.stackexchange.com/questions/136206/readarray-or-pipe-issue - @ dave_thompson_085 La commande
bash
peut être exécutée dans le shell supérieur en fonction des options, maisx=42
sera certainement exécuté dans quelque chose qui peut raisonnablement être appelé un sous-shell. - @AlexanderMills En fait, le tube nest pas ' t le seul problème. La commande
bash
exécutera son entrée dans un sous-shell indépendamment du fait quun tube soit impliqué ou non. Voir la mise à jour de ma solution pour plus de détails.
( eval 'echo "foo"' )