Variables d'environnement vs paramètres positionnels
Avant de commencer à discuter du $INTEGERtype de variables, nous devons comprendre ce qu'elles sont réellement et comment elles diffèrent des variables d'environnement. Des variables telles que $INTEGERles paramètres de position sont appelées. Ceci est décrit dans la norme POSIX (Portable Operating System Interface), section 2.1 (accent sur le mien):
- Le shell exécute une fonction (voir Commande de définition de fonction), intégrée (voir Utilitaires intégrés spéciaux), un fichier exécutable ou un script, donnant les noms des arguments sous forme de paramètres positionnels numérotés de 1 à n, et le nom de la commande (ou dans le cas d'une fonction dans un script, le nom du script) comme paramètre positionnel numéroté 0 (voir Recherche et exécution de commandes).
En revanche, des variables telles que $HOMEet $PATHsont des variables d'environnement. Leur définition est décrite dans la section 8 de la norme :
Les variables d'environnement définies dans ce chapitre affectent le fonctionnement de plusieurs utilitaires, fonctions et applications. Il existe d'autres variables d'environnement qui ne présentent d'intérêt que pour des utilitaires spécifiques. Les variables d'environnement qui s'appliquent à un seul utilitaire sont définies dans le cadre de la description de l'utilitaire.
Remarquez leur description. Les paramètres de position sont censés apparaître devant une commande, c'est-à-dire command positional_arg_1 positional_arg_2.... Ils sont destinés à être fournis par l'utilisateur pour indiquer à la commande quoi faire spécifiquement. Lorsque vous le faites echo 'Hello' 'World', il imprimera les chaînes Helloet World, car ce sont des paramètres de position pour echo- les choses sur lesquelles vous souhaitez echoopérer. Et echoest construit de telle sorte qu'il comprend les paramètres de position comme des chaînes à imprimer (à moins qu'ils ne soient l'un des indicateurs optionnels comme -n). Si vous faites cela avec une commande différente, il pourrait ne pas comprendre quoi HelloetWorldest parce qu'il attend peut-être un certain nombre. Notez que les paramètres positionnels ne sont pas "hérités" - un processus enfant ne connaît pas les paramètres positionnels du parent sauf s'il est explicitement transmis au processus enfant. Souvent, vous voyez des paramètres positionnels passés avec des scripts wrapper - ceux qui peuvent vérifier l'instance déjà existante d'une commande ou ajouter des paramètres positionnels supplémentaires à la commande réelle qui sera appelée.
En revanche, les variables d'environnement sont censées affecter plusieurs programmes. Ce sont des variables d' environnement , car elles sont définies en dehors du programme lui-même (plus d'informations ci-dessous). Certaines variables d'environnement telles que HOMEou PATHont un format spécifique, une signification spécifique, et elles auront la même signification pour chaque programme. HOMELa variable aura la même signification pour un utilitaire externe comme pour /usr/bin/findvotre shell (et par conséquent pour un script) - c'est le répertoire personnel du nom d'utilisateur sous lequel le processus s'exécute. Notez que les variables d'environnement peuvent être utilisées pour tenir compte d'un comportement de commande spécifique, par exempleUIDLa variable d'environnement peut être utilisée pour vérifier si le script s'exécute avec les privilèges root ou non et se ramifier à des actions spécifiques en conséquence. Les variables d'environnement sont héritables - les processus enfants obtiennent une copie de l'environnement du parent. Voir aussi Si les processus héritent de l'environnement du parent, pourquoi avons-nous besoin d'exporter?
En bref, la principale distinction est que les variables d'environnement sont définies en dehors de la commande et ne sont pas censées être modifiées (généralement), tandis que les paramètres de position sont des choses qui sont censées être traitées par la commande et changent.
Pas seulement des concepts shell
Ce que j'ai remarqué dans les commentaires, c'est que vous mélangez terminal et shell, et je vous recommande vraiment de lire sur les vrais terminaux qui étaient autrefois des appareils physiques. De nos jours, le "terminal" auquel nous nous référons généralement, cette fenêtre avec un fond noir et du texte vert est en fait un logiciel, un processus. Terminal est un programme qui exécute un shell, tandis que shell est également un programme mais celui qui lit ce que vous tapez pour exécuter (c'est-à-dire s'il s'agit d'un shell interactif; les shells non interactifs sont des scripts et des sh -c 'echo foo'types d'appels). Plus d'informations sur les obus ici .
Il s'agit d'une distinction importante, mais il est également important de reconnaître que le terminal est un programme et adhère donc aux mêmes règles d'environnement et de paramètres de position. Votre gnome-terminaldémarrage commencera à regarder votre SHELLvariable d'environnement et générera le shell par défaut approprié pour vous, sauf si vous spécifiez une autre commande avec -e. Disons que j'ai changé mon shell par défaut en ksh - gnome-terminal apparaîtra alors à la kshplace de bash. C'est également un exemple de la façon dont l'environnement est utilisé par les programmes. Si je dis explicitement à gnome-terminalavec -ed'exécuter un shell spécifique - il le fera, mais ce ne sera pas permanent. En revanche, l'environnement est censé être essentiellement inchangé (plus à ce sujet plus tard).
Donc, comme vous pouvez le voir, les variables d'environnement et de position sont toutes les deux des propriétés d'un processus / commande, pas seulement un shell. En ce qui concerne les scripts shell, ils suivent également le modèle défini par le langage de programmation C. Prenons par exemple la mainfonction C qui ressemble généralement à
int main(int argc, char **argv)
, où argcest le nombre d'arguments de ligne de commande et argvest effectivement un tableau de paramètres de ligne de commande, et puis il y a une environfonction (sous Linux c'est man -e 7 environ) pour accéder à des choses comme le chemin du répertoire personnel de l'utilisateur, la liste des répertoires dans PATHlesquels nous pouvons rechercher des exécutables, etc. Les scripts shell sont également modélisés de la même manière. Dans la terminologie shell, nous avons des paramètres positionnels $1, $2et ainsi de suite, tandis que $#est le nombre de paramètres positionnels. Et alors $0? C'est le nom de l'exécutable lui-même, qui est également modélisé à partir du langage de programmation C - argv[0]serait le nom de votre "exécutable" C. Et cela est assez vrai pour la plupart des langages de programmation et de script .
Coquilles interactives vs non interactives
J'ai déjà fait allusion à la distinction entre les shells interactifs et non interactifs . L'invite où vous tapez des commandes - c'est interactif, il interagit avec l'utilisateur. En revanche, lorsque vous avez un script shell ou que vous exécutez bash -c''ce n'est pas interactif.
Et c'est là que la distinction devient importante. Le shell que vous exécutez déjà est un processus qui a été généré avec des paramètres de position (pour le bashshell de connexion est un "... dont le premier caractère de l'argument zéro est un -, ou un a commencé avec l'option --login." ( Référence ) )
En revanche, les scripts et les shells lancés avec -coption peuvent tirer parti des arguments $1et $2. Par exemple,
$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
File: '/etc/passwd'
Size: 2913 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6035604 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
Birth: -
Notez que j'y ai également utilisé sh, car une petite bizarrerie d' -coption est de prendre le premier paramètre positionnel et de l'affecter à $0, contrairement au nom typique du programme.
Une autre chose qui est importante à noter est que les paramètres de position sont ce que j'appelle "framable". Remarquez comment, nous avons d'abord lancé bashavec ses propres paramètres de position, mais ces paramètres de position sont devenus des paramètres pour echoet stat. Et chaque programme le comprend à sa manière. Si nous donnions à statune chaîne Hello Worldet qu'il n'y avait pas de fichier, Hello Worldcela produirait une erreur; bashla traite comme une simple chaîne mais stats'attend à ce que cette chaîne soit un nom de fichier existant. En revanche, tous les programmes conviennent que la variable d'environnement HOMEest un répertoire (à moins que le programmeur ne l'ait codé de manière déraisonnable).
Pouvons-nous jouer avec les variables d'environnement et les paramètres de position?
Techniquement, nous pouvons jouer avec les deux, mais nous ne devrions pas jouer avec les variables d'environnement, alors que nous devons souvent fournir des paramètres de position. Nous pouvons exécuter des commandes dans le shell en ajoutant une variable, par exemple:
$ hello=world bash -c 'echo $hello'
world
Nous pouvons également placer des variables dans l'environnement en utilisant simplement à export variable=valuepartir du shell ou du script. Ou nous pouvons exécuter une commande avec un environnement complètement vide avec env -c command arg1 arg2. Cependant, il n'est généralement pas recommandé de jouer avec l'environnement, en particulier en utilisant des variables majuscules ou en remplaçant des variables d'environnement déjà existantes. Notez que c'est recommandé mais pas standard.
Pour les paramètres de position, la façon de les définir est évidente, il suffit de les ajouter à la commande, mais il existe également des moyens de les définir autrement , ainsi que de modifier la liste de ces paramètres via la shiftcommande.
En conclusion, le but de ces deux est différent, et ils existent pour une raison. J'espère que les gens ont acquis un aperçu de cette réponse, et c'était amusant de la lire tout comme c'était pour moi d'écrire cette réponse.
Remarque sur la commande set
La setcommande, selon le manuel, se comporte ainsi (à partir du manuel bash, emphase ajoutée):
Sans options, le nom et la valeur de chaque variable shell sont affichés dans un format qui peut être réutilisé en entrée pour définir ou réinitialiser les variables actuellement définies.
En d'autres termes, setexamine les variables spécifiques au shell, dont certaines se trouvent dans l'environnement, par exemple HOME. En revanche, les commandes aiment envet printenvregardent la variable d'environnement réelle avec laquelle une commande s'exécute. Voir aussi ceci .
export 3vous transformer$3en variable d'environnement. Vous ne pouvez pasunset 3; et vous ne pouvez pas attribuer$3une nouvelle valeur à l'aide de3=val.