J'ai une commande stockée dans une variable. Imaginons que la variable $i
ait la valeur:
cat -nT index.php |grep 'someregex'
Lorsque j'essaie d'exécuter la variable ci-dessus en la tapant, $i
elle échoue car le shell tente d'exécuter la variable entière en une seule commande. J'ai également essayé d'utiliser eval($i)
et de mettre des $i
backticks.
Comment puis-je faire exécuter le shell $i
comme s'il s'agissait d'une commande? Et pourquoi ne fonctionne-t-il pas de la même manière que.
$i='echo hi'; $i
Est-ce parce que je devais en quelque sorte pirater les guillemets simples? (Parce que vous ne pouvez pas les imbriquer.) Actuellement, ma solution est
echo $i > /foo; . /foo
Mais je ne veux pas avoir créé un fichier juste pour cela, seulement pour le supprimer plus tard.
Ce que je veux dire par «j'ai piraté les guillemets simples, c'est que j'ai fait:
$i='cat index.php | grep -P '"'"'MYREGEXHERE'"'"
Réponses:
Réponse courte: voir BashAQ # 50: J'essaie de mettre une commande dans une variable, mais les cas complexes échouent toujours! .
Réponse longue: c'est à cause de l'ordre dans lequel bash analyse la ligne de commande. Plus précisément, il recherche des éléments tels que les tuyaux et les redirections avant d'étendre les valeurs variables, et ne revient pas en arrière et ne recherche pas les tuyaux, etc. dans les valeurs développées. Essentiellement, les variables sont substituées à mi-chemin du processus d'analyse, de sorte que la valeur n'est analysée qu'à mi-chemin avant d'être exécutée.
Pour résoudre ce problème, vous devez répondre à la question de @ slhck: pourquoi la commande est-elle stockée dans une variable en premier lieu? Quel est le problème réel que vous essayez de résoudre? Selon l'objectif réel, plusieurs solutions sont possibles:
Ne le stockez pas dans une variable, exécutez-le simplement directement. Stocker des commandes pour une utilisation ultérieure est délicat, et si vous n'en avez pas vraiment besoin, tout simplement pas.
Utilisez une fonction au lieu d'une variable. C'est à cela qu'ils servent, après tout:
Le principal inconvénient de cela est que vous ne pouvez pas créer la fonction dynamiquement - vous ne pouvez pas inclure ou exclure conditionnellement du code de la fonction (bien que la fonction elle-même puisse avoir des éléments conditionnels qui sont sélectionnés lors de son exécution).
Utilisez
eval
. Cela devrait être considéré comme un dernier recours, car il est facile d'obtenir un comportement inattendu. Il exécute essentiellement la commande via une autre passe d'analyse complète, de sorte que tous les canaux, etc. obtiennent leur pleine signification - mais cela signifie également que des parties de la commande que vous pensiez être uniquement des données seront également analysées et peut-être exécutées. Les noms de fichiers qui contiennent des métacaractères shell (pipe, point-virgule, citation / apostrophe, etc.) peuvent avoir des effets étranges et parfois dangereux. Si vous utilisezeval
, au moins entre guillemets, la chaîne, sinon son contenu est essentiellement analysé une fois et demie, avec des résultats encore plus étranges.EDIT: Une autre approche standard de stockage d'une commande dans une variable consiste à utiliser un tableau au lieu d'une simple variable. Cela vous permet de stocker une commande avec des arguments complexes (par exemple contenant des espaces) sans problème, mais ne stockera pas des choses comme les tuyaux et les redirections. Ainsi, l'approche tableau ne sera pas utile dans ce cas particulier.
la source
eval
méthode. Cela m'a empêché de poser la même question :). J'ai quelque chose commesudo rsync -aAHXi -n --delete-excluded --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/lost+found","/mnt/DATA/*","/var/log/*","/var/swap","/var/cache/apt/archives/*.deb"} -e ssh root@piac_wireless:/ /home/mrx/Docs/RPi/backup/piac/piac_usb-root
ça qui n'exécutait pas correctement les exclusions.eval
pour cela - il y a trop de façons pour que ça se passe mal. Un tableau serait une meilleure façon de le faire. Voir ici , ici et ici pour des exemples.Cela devrait simplement fonctionner:
Attention, qui
eval
introduit des vulnérabilités potentielles et des situations de comportement inattendues doit donc être utilisé, si jamais, avec plus de prudence.la source
eval
, vous devez vraiment utiliser des guillemets doubles (eval "$i"
) pour éviter les effets extra-extra-bizarres. Par exemple, essayez ceci aveca="cat -nT index.php |grep ' .* '"
(c'est-à-dire que l'expression régulière doit correspondre à deux espaces avec n'importe quelle séquence de caractères entre eux) et voyez ce qui se passe réellement. Pour un crédit supplémentaire, expliquez pourquoi cela se produit.Lors de la déclaration de la variable, vous ne devez pas utiliser le signe dollar comme préfixe.
Essaye ça:
la source