Normalement, il est possible de définir une variable d'environnement pour une commande en la préfixant comme ceci:
hello=hi bash -c 'echo $hello'
Je sais également que nous pouvons utiliser une variable pour remplacer n'importe quelle partie d'un appel de commande comme suit:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
J'ai été très surpris de découvrir que vous ne pouvez pas utiliser une variable pour préfixer une commande pour définir une variable d'environnement. Cas de test:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Pourquoi ne puis-je pas définir la variable d'environnement à l'aide d'une variable? La partie préfixe est-elle une partie spéciale? J'ai pu le faire fonctionner en utilisant eval en face, mais je ne comprends toujours pas pourquoi. J'utilise bash 4.4.
env
place deeval
, lequel IIRC est plus sûr, mais plus lent.Réponses:
Je soupçonne que c'est la partie de la séquence qui vous rattrape:
Cela provient du manuel de référence Bash dans la section sur l'extension de commande simple.
Dans l'
cmd=bash
exemple, aucune variable d'environnement n'est définie et bash traite la ligne de commande via l'expansion des paramètres, laissantbash -c "echo hi"
.Dans l'
prefix=hello=hi
exemple, il n'y a à nouveau aucune affectation de variable lors de la première passe, donc le traitement continue l'expansion des paramètres, ce qui donne un premier mot dehello=hi
.Une fois que les affectations de variables ont été traitées, elles ne sont pas retraitées pendant l'exécution de la commande.
Voir le traitement et ses résultats sous
set -x
:Pour une variation plus sûre de "l'expansion variable" -en tant que "variables d'environnement"
eval
, considérez la suggestion de wjandreaenv
:Ce n'est pas strictement une affectation de variable en ligne de commande, car nous utilisons la
env
fonction principale de l' utilitaire d'affecter des variables d'environnement à une commande, mais elle atteint le même objectif. La$prefix
variable est développée pendant le traitement de la ligne de commande, fournissant le nom = valeur àenv
, qui la transmet àbash
.la source
$foo=bar bash -c ...
ne fonctionnera pas, car il$foo=bar
ne s'agit pas d'une affectation de variable (quelle que soit la valeur de$foo
), car$foo=bar
ne correspond pas auname=value
modèle d'affectation de variable.Parce que ce
$prefix
n'est pas une mission. @Jeff a l'explication la plus longue .Vous pouvez faire une chose similaire avec une fonction à la place:
... et vous pouvez même les empiler si vous le souhaitez:
la source