De temps en temps, je rédige un script bash et il me semble qu'il existe plusieurs façons de définir une variable:
key=value
env key=value
export key=value
Lorsque vous êtes dans un script ou une seule commande (par exemple, je vais souvent chaîner une variable avec un lanceur Wine pour définir le préfixe Wine correct), celles-ci semblent être complètement interchangeables, mais ce ne peut certainement pas être le cas.
Quelle est la différence entre ces trois méthodes et pouvez-vous me donner un exemple du moment où je souhaiterais spécifiquement utiliser chacune d'elles?
Certainement lié à Quelle est la différence entre `VAR = ...` et `export VAR = ...`? mais je veux savoir comment env
s'inscrit également dans ceci, et quelques exemples montrant les avantages de chacun serait bien aussi :)
Considérons un exemple spécifique. La commande grep
utilise une variable d'environnement appelée GREP_OPTIONS
pour définir les options par défaut.
À présent. Étant donné que le fichier test.txt
contient les lignes suivantes:
line one
line two
l'exécution de la commande grep one test.txt
retournera
line one
Si vous exécutez grep avec l’option -v
, les lignes qui ne correspondent pas seront renvoyées, ainsi le résultat sera
line two
Nous allons maintenant essayer de définir l'option avec une variable d'environnement.
Les variables d'environnement définies sans export
ne seront pas héritées de l'environnement des commandes que vous appelez.
GREP_OPTIONS='-v'
grep one test.txt
Le résultat:
line one
De toute évidence, l'option -v
n'a pas été transmise à grep
.
Vous souhaitez utiliser ce formulaire lorsque vous définissez une variable à utiliser uniquement par le shell, par exemple, dans for i in * ; do
, vous ne souhaitez pas exporter $i
.
Cependant, la variable est transmise à l'environnement de cette ligne de commande, vous pouvez donc effectuer
GREP_OPTIONS='-v' grep one test.txt
qui retournera le prévu
line two
Vous utilisez ce formulaire pour modifier temporairement l'environnement de cette instance particulière du programme lancé.
L'exportation d'une variable entraîne l'héritage de la variable:
export GREP_OPTIONS='-v'
grep one test.txt
revient maintenant
line two
C'est le moyen le plus courant de définir des variables pour l'utilisation de processus démarrés ultérieurement dans un shell
Tout a été fait à Bash. export
est une bash intégrée; VAR=whatever
est la syntaxe bash. env
, d'autre part, est un programme en soi. Lorsque env
est appelé, les événements suivants se produisent:
env
est exécutée en tant que nouveau processus.env
modifie l'environnement, etenv
est remplacé par le processus command
.Exemple:
env GREP_OPTIONS='-v' grep one test.txt
Cette commande lancera deux nouveaux processus: (i) env et (ii) grep (en réalité, le deuxième processus remplacera le premier). Du point de vue du processus grep
, le résultat est exactement identique à l'exécution
GREP_OPTIONS='-v' grep one test.txt
Cependant, vous pouvez utiliser cet idiome si vous êtes en dehors de bash ou si vous ne souhaitez pas lancer un autre shell (par exemple, lorsque vous utilisez la famille de fonctions exec()
plutôt que l'appel system()
).
Note complémentaire sur #!/usr/bin/env
C'est aussi pourquoi l'idiome #!/usr/bin/env interpreter
est utilisé plutôt que #!/usr/bin/interpreter
. env
ne nécessite pas un chemin complet pour un programme, car il utilise la fonction execvp()
qui recherche dans la variable PATH
comme le fait un shell, puis remplace lui-même par la commande exécuter. Ainsi, il peut être utilisé pour savoir où un interprète (comme Perl ou python) "se repose" sur le chemin.
Cela signifie également qu'en modifiant le chemin actuel, vous pouvez influencer la variante python qui sera appelée. Cela rend possible ce qui suit:
echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre
au lieu de lancer Calibre, il en résultera
I am an evil interpreter!