web-dev-qa-db-fra.com

Comment exécuter une commande stockée dans une variable?

Quelle est la bonne façon d'appeler une commande stockée dans variable?
Y at-il des différences entre 1 et 2?

#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
77
Volodymyr Bezuglyy

Les shells Unix effectuent une série de transformations sur chaque ligne d’entrée avant de les exécuter. Pour la plupart des shells, cela ressemble à ceci (tiré de la page de manuel bash):

  • fractionnement initial du mot
  • expansion du corset
  • expansion de tilde
  • expansion de paramètre, variable et arithmétique
  • substitution de commande
  • division de mots secondaire
  • extension de chemin (aka globbing)
  • suppression de devis

En utilisant $cmd le récupère directement par votre commande lors de la phase de développement des paramètres, puis il subit toutes les transformations suivantes.

En utilisant eval "$cmd" ne fait rien jusqu’à la phase de suppression des devis, où $cmd est retourné tel quel et passé comme paramètre à eval, dont la fonction est de réexécuter toute la chaîne avant de l'exécuter.

En gros, ils sont identiques dans la plupart des cas et diffèrent lorsque votre commande utilise les étapes de transformation pour développer les paramètres. Par exemple, en utilisant l’accolade:

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz
88
JB.

Si vous ne faites que eval $cmd quand on fait cmd="ls -l" (de manière interactive et dans un script), nous obtenons le résultat souhaité. Dans votre cas, vous avez un tube avec un grep sans motif, donc la partie grep échouera avec un message d'erreur. Juste $cmd générera un message "commande introuvable" (ou un message similaire). Essayez donc d'utiliser eval et d'utiliser une commande terminée, pas une qui génère un message d'erreur.

5
Henno Brandsma

$cmd _ remplacerait simplement la variable par sa valeur à exécuter en ligne de commande. eval "$cmd" effectue une extension de variable et une substitution de commande avant d'exécuter la valeur résultante en ligne de commande

La deuxième méthode est utile lorsque vous souhaitez exécuter des commandes qui ne sont pas flexibles, par exemple.
for i in {$a..$b}
La boucle de formatage ne fonctionnera pas car elle n'autorise pas les variables.
Dans ce cas, une pipe à bash ou à eval est une solution de contournement.

testé sur Mac OSX 10.6.8, Bash 3.2.48

0
Zimba