Si je cours
export TEST=foo
echo $TEST
Il produit foo.
Si je cours
TEST=foo echo $TEST
Ce ne est pas. Comment puis-je obtenir cette fonctionnalité sans utiliser l'exportation ou un script?
C'est parce que le Shell développe la variable dans la ligne de commande avant il exécute réellement la commande et à ce moment la variable n'existe pas. Si tu utilises
TEST=foo; echo $TEST
ça va marcher.
export
fera apparaître la variable dans l'environnement des commandes exécutées ultérieurement (pour savoir comment cela fonctionne en bash, voir help export
). Si vous avez seulement besoin que la variable apparaisse dans l'environnement d'une commande, utilisez ce que vous avez essayé, à savoir:
TEST=foo your-application
Je soupçonne que vous voulez avoir des variables Shell pour avoir une portée limitée, plutôt que des variables d'environnement. Les variables d'environnement sont une liste de chaînes passées aux commandes lorsqu'elles sont exécutées.
Dans
var=value echo whatever
Vous passez le var=value
chaîne vers l'environnement reçu par l'écho. Cependant, echo
ne fait rien avec sa liste d'environnement¹ et de toute façon dans la plupart des shells, echo
est intégré et donc pas exécuté .
Si vous aviez écrit
var=value sh -c 'echo "$var"'
Cela aurait été une autre affaire. Ici, on passe var=value
à la commande sh
, et sh
utilise son environnement. Les shells convertissent chacune des variables qu'ils reçoivent de leur environnement en une variable Shell, donc la variable d'environnement var
sh
reçoit sera convertie en $var
variable, et lorsqu'elle l'étend dans cette ligne de commande echo
, elle devient echo value
. Étant donné que l'environnement est hérité par défaut, echo
recevra également var=value
dans son environnement (ou le ferait s'il était exécuté), mais encore une fois, echo
ne se soucie pas de l'environnement.
Maintenant, si comme je le soupçonne, ce que vous voulez, c'est limiter la portée des variables Shell, il existe plusieurs approches possibles.
Portable (Bourne et POSIX):
(var=value; echo "1: $var"); echo "2: $var"
Le (...) ci-dessus démarre un sous-shell (un nouveau processus Shell dans la plupart des shells), donc toute variable déclarée ici n'affectera que ce sous-shell, donc je m'attendrais à ce que le code ci-dessus produise "1: valeur" et "2:" ou "2: quelle que soit-var-was-set-to-before".
Avec la plupart des shells de type Bourne, vous pouvez utiliser des fonctions et le builtin "local":
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Avec zsh, vous pouvez utiliser des fonctions en ligne:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
ou:
function { local var=value; echo "1: $var"; }; echo "2: $var"
Avec bash et zsh (mais pas ash, pdksh ou AT&T ksh), cette astuce fonctionne également:
var=value eval 'echo "1: $var"'; echo "2: $var"
Une variante qui fonctionne dans quelques autres shells (dash
, mksh
, yash
) mais pas zsh
(sauf dans sh
/ksh
émulation):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(l'utilisation de command
devant un module spécial spécial (ici eval
) dans les shells POSIX supprime leur particularité (ici, les affectations de variables à partir d'eux restent en vigueur après leur retour))
¹ Strictement parlant, ce n'est pas tout à fait vrai. Plusieurs implémentations se soucieront des variables d'environnement de localisation (LANG
, LOCPATH
, LC_*
...), l'implémentation GNU se soucie de POSIXLY_CORRECT
variable d'environnement (comparer env echo --version
avec POSIXLY_CORRECT=1 env echo --version
sur un GNU).
Vous le faites correctement, mais la syntaxe bash est facile à mal interpréter: vous pourriez penser que echo $TEST
fait que echo
récupère TEST
env var puis l'imprime, ce n'est pas le cas. Donc donné
export TEST=123
puis
TEST=456 echo $TEST
implique la séquence suivante:
Le shell analyse toute la ligne de commande et exécute toutes les substitutions de variables, de sorte que la ligne de commande devient
TEST=456 echo 123
Il crée les variables temporaires définies avant la commande, il enregistre donc la valeur actuelle de TEST
et l'écrase avec 456; la ligne de commande est maintenant
echo 123
Il exécute la commande restante, qui dans ce cas imprime 123 sur stdout (donc la commande Shell qui reste n'a même pas utilisé la valeur temporaire de TEST
)
Il restaure la valeur de TEST
Utilisez plutôt printenv, car cela n'implique pas de substitution de variable:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
Vous pouvez faire fonctionner cela en utilisant:
TEST=foo && echo $TEST