Il existe des variables dans la coquille comme $0
, $1
, $2
, $?
, etc.
J'ai essayé d'imprimer le shell et les variables d'environnement à l'aide de la commande suivante:
set
Mais ces variables n'étaient pas dans la liste.
Donc, fondamentalement, ces variables ne sont pas considérées comme des variables shell / environnement, non? (même si pour les sortir, vous devez les faire précéder d'un $
, comme vous le faites avec les variables shell / environnement)
export 3
vous transformer$3
en variable d'environnement. Vous ne pouvez pasunset 3
; et vous ne pouvez pas attribuer$3
une nouvelle valeur à l'aide de3=val
.Réponses:
Les variables sont l'une des trois variétés distinctes de paramètres dans le shell.
_
ou une lettre, suivie de zéro ou plusieurs lettres, chiffres ou_
.$1
,$2
...$0
, ce sont tous des caractères de ponctuation différents.set
affiche uniquement les variables du shell.Un sous-ensemble des variables du shell sont les variables d'environnement, dont les valeurs sont soit héritées de l'environnement au démarrage du shell, soit créées en définissant l'
export
attribut sur un nom valide.la source
set
affiche tous les paramètres danszsh
(pas $ 1, $ 2 ... mais $ *, $ @) et les fonctions dans bash et bosh. Certains shells comme ksh93 et les anciennes versions des vars env de sortie de tiret qui n'étaient pas mappés à des variables de shell. (env 1=foo ksh -c set
imprimerait1=foo
)Variables d'environnement vs paramètres positionnels
Avant de commencer à discuter du
$INTEGER
type de variables, nous devons comprendre ce qu'elles sont réellement et comment elles diffèrent des variables d'environnement. Des variables telles que$INTEGER
les 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):En revanche, des variables telles que
$HOME
et$PATH
sont des variables d'environnement. Leur définition est décrite dans la section 8 de la norme :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 faitesecho 'Hello' 'World'
, il imprimera les chaînesHello
etWorld
, car ce sont des paramètres de position pourecho
- les choses sur lesquelles vous souhaitezecho
opérer. Etecho
est 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 quoiHello
etWorld
est 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
HOME
ouPATH
ont un format spécifique, une signification spécifique, et elles auront la même signification pour chaque programme.HOME
La variable aura la même signification pour un utilitaire externe comme pour/usr/bin/find
votre 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 exempleUID
La 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-terminal
démarrage commencera à regarder votreSHELL
variable 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 enksh
- gnome-terminal apparaîtra alors à laksh
place debash
. C'est également un exemple de la façon dont l'environnement est utilisé par les programmes. Si je dis explicitement àgnome-terminal
avec-e
d'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
main
fonction C qui ressemble généralement à, où
argc
est le nombre d'arguments de ligne de commande etargv
est effectivement un tableau de paramètres de ligne de commande, et puis il y a uneenviron
fonction (sous Linux c'estman -e 7 environ
) pour accéder à des choses comme le chemin du répertoire personnel de l'utilisateur, la liste des répertoires dansPATH
lesquels 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
,$2
et 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
bash
shell 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
-c
option peuvent tirer parti des arguments$1
et$2
. Par exemple,Notez que j'y ai également utilisé
sh
, car une petite bizarrerie d'-c
option 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é
bash
avec ses propres paramètres de position, mais ces paramètres de position sont devenus des paramètres pourecho
etstat
. Et chaque programme le comprend à sa manière. Si nous donnions àstat
une chaîneHello World
et qu'il n'y avait pas de fichier,Hello World
cela produirait une erreur;bash
la traite comme une simple chaîne maisstat
s'attend à ce que cette chaîne soit un nom de fichier existant. En revanche, tous les programmes conviennent que la variable d'environnementHOME
est 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:
Nous pouvons également placer des variables dans l'environnement en utilisant simplement à
export variable=value
partir du shell ou du script. Ou nous pouvons exécuter une commande avec un environnement complètement vide avecenv -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
shift
commande.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
set
commande, selon le manuel, se comporte ainsi (à partir du manuel bash, emphase ajoutée):En d'autres termes,
set
examine les variables spécifiques au shell, dont certaines se trouvent dans l'environnement, par exempleHOME
. En revanche, les commandes aimentenv
etprintenv
regardent la variable d'environnement réelle avec laquelle une commande s'exécute. Voir aussi ceci .la source
1="foo"
mais plus tard, j'ai découvert que par définition POSIX, un "mot" (c'est-à-dire le nom d'un objet tel qu'une variable ou une fonction) ne peut pas commencer avec un chiffre (voir une question que j'ai postée sur le sujet ). Les paramètres de position font apparemment exception à cette règle.$1
,$2
et ainsi de suite dans le shell interactif, et en fait, cela se fait avec laset
commande, souvent pour contourner la/bin/sh
limitation de ne pas avoir de tableaux. Merci d'avoir porté cela à mon attention. Je vais également modifier la réponse au cours des prochains jours, car elle a besoin d'un peu de polissage supplémentaire et d'une mise à jour.conda
, lorsque vous exécutezsource conda/bin/activate
, il vérifie si$1
,$2
etc., sont fixés, afin de déterminer si elle a été exécuté comme un script avec des arguments ou non. Cela finit par casser sur les systèmes qui ont ceux définis dans l'environnement interactif pour une raison quelconque. J'espère savoir si ce comportement non standard est une faille dans le système pour définir ces variables dans l'environnement interactif, ou dans le programme pour les utiliser pour déterminer s'il a été exécuté comme script.conda
développeurs ou à quiconque est l'auteur original d'un tel script, car la vérification des${N}
paramètres n'est certainement pas la bonne solution. Il y a des questions sur le même sujet ici et ici , et le moyen plus ou moins portable consiste à vérifier s'il${0}
est identique au nom du script, toutbash
en ayant une variable d'environnement à cet effetLes
$1, $2, $3, ..., ${10}, ${11}
variables sont appelées paramètres de position et sont couvertes dans la section du manuel bash3.4.1
Quant à
$?
et$0
, ces paramètres spéciaux sont traités dans la section suivante3.4.2
la source
$1
,$2
... sont des paramètres de position , ce ne sont pas des variables, encore moins des variables d'environnement.Dans Bourne-shell comme la terminologie,
$something
est appelée paramètre expansion (couvre aussi${something#pattern}
et plus dans certains coquillages comme${array[x]}
,${param:offset}
,${x:|y}
et de nombreux opérateurs plus d'expansion).Il existe différents types de paramètres:
$foo
,$PATH
$1
,$2
... les arguments reçus par votre script)$0
,$-
,$#
,$*
,$@
,$$
,$!
,$?
...les noms de variables dans Bourne comme les shells doivent commencer par un caractère alphabétique (tout reconnu par les paramètres régionaux ou limité à a-zA-Z selon le shell) et souligner et suivi de zéro ou plusieurs caractères alphanumériques ou traits de soulignement.
Selon le shell, les variables peuvent avoir différents types (scalaire, tableau, hachage) ou avoir certains attributs (lecture seule, exporté, minuscule ...).
Certaines de ces variables sont créées par le shell ou ont une signification particulière à la coque (comme
$OPTIND
,$IFS
,$_
...)Les variables shell qui ont l' attribut export sont automatiquement exportées en tant que variables d'environnement vers les commandes que le shell exécute.
La variable d'environnement est un concept distinct des variables shell. L'exportation d'une variable shell n'est pas le seul moyen de passer une variable d'environnement à l'exécution d'une commande.
passera une
VAR
variable d'environnement à laprintenv
commande (que nous indiquons pour imprimer son contenu), mais vous pouvez également faire:ou:
par exemple.
Les variables d'environnement peuvent avoir n'importe quel nom (peuvent contenir n'importe quel caractère mais
=
peuvent même être vides). Ce n'est pas une bonne idée de donner un nom qui n'est pas compatible avec celui d'un nom de variable shell de type Bourne à une variable d'environnement, mais c'est possible:Les shells mapperont les variables d'environnement qu'ils reçoivent en variables de shell uniquement pour les variables d'environnement dont le nom est des variables de shell valides (et dans certains shells, ignorez certaines spéciales comme
$IFS
).Ainsi, alors que vous seriez en mesure de passer une
1
variable d'environnement à une commande:Cela ne signifie pas que l'appel d'un shell avec cette variable d'environnement définirait la valeur du
$1
paramètre:la source
Non, ce sont des paramètres du script. Par exemple, si vous appelez votre script comme:
puis à l'intérieur du script, ces paramètres seront disponibles en tant que
et le $ 0 est le nom du script lui-même.
Donc, lorsque vous êtes en dehors du script, ces variables ne sont pas disponibles (sauf $ 0, qui affiche / bin / bash - le shell lui-même).
la source
$0
pointera vers votre processus terminal actuel (probablement bash) et$?
est simplement le code de sortie du dernier processus.gnome-terminal
argument with (gnome-terminal Hello World
). Je pouvais voir$0
, mais je ne pouvais pas voir$1
et$2
.