eval vs pipe through bash (Français)

Quelle est la différence entre utiliser:

eval "echo "foo"" 

et

echo "echo "foo"" | bash 

y en a-t-il?

Commentaires

  • Ici ' est une autre variante avec un comportement légèrement différent quant aux environnements dexécution: ( eval 'echo "foo"' )

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, mais x=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.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *