Quelle est la signification de «_ =»?

29

Après avoir exécuté le set -a var=99, je peux trouver une phrase dans la sortie de set:

...
TERM=xterm
UID=0
USER=root
VIRTUAL_ENV_DISABLE_PROMPT=1
_=var=99
colors=/etc/DIR_COLORS
...

Quelqu'un pourrait-il me dire ce que "_ =" signifie?

Je note que cela echo $varne donnera rien. Si je lance le set -a, alors le setne comprendra plus cette variable. Qu'est-ce qui se passe?

Yo de
la source

Réponses:

16

Lorsque vous exécutez set -a var=99, trois choses distinctes se produisent (liées à votre question):

  1. Une option définie ( -a) (inverser en faisant set +a) pour exporter les variables.
  2. Les paramètres de position sont "définis" sur ce qui suit les options ( $1définis sur var=99).
  3. Le trait de soulignement de la variable shell $_est défini sur le dernier paramètre (développé).

set -a

L'exécution de set -amarque toutes les variables suivantes (nouvelles ou modifiées) comme exportées (dans tous les shells, à l'exception de cshcertains shells associés).

$ set -a
$ myvariable=wer
$ env | grep myvariable
myvariable=wer

Pour récupérer à partir de ce paramètre, changez simplement le -en a +:

$ set +a
$ unset myvariable              # to erase it from the environment if it
                                # was exported before the change of set +a
$ myvariable=456544654          # A new value of the variable.
$ env | grep "variable"         # No output means the var does not exist
                                # in the current environment

définir var = 99

Ce qui devrait en fait être set -- var=99d'éviter l'interprétation d'une option (et set a beaucoup) avec des valeurs qui commencent par un tiret ( -).

Définit la liste des arguments (la liste des paramètres de position) sur celle après le --. Cela est valable dans tous les shells raisonnables (pas dans csh et al). Les arguments positionnels sont imprimés avec "$ @" (ou similaire "$ *", différent).

$ set -- a=1 b=2 c=3
$ echo "$@"
a=1 b=2 c=3

_ = dernier_argument

Et, la valeur de la variable shell interne devient _le dernier argument de la ligne exécutée. Ce n'est PAS vrai dans presque tous les shells (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh et bien sûr csh et tcsh) sauf bash.

$ echo one two last argument
one two last argument

$ echo "$_"
argument

$ echo This is a new: last_argument
This is a new: last_argument

$ echo "$_"
last_argument

Veuillez noter que la valeur en $_est la valeur après expansion:

$ a="A New_Argument"
$ echo Something else to test: "$a"
Something else to test: A New_Argument

$ echo "$_"
A New_Argument

C'est pourquoi lorsque vous exécutez:

$ set -a myvar=99; set | grep 'myvar'
_=myvar=99

Vous obtenez une description de la variable shell '$ _'. Cela fonctionne également:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"
Flèche
la source
37

Le trait de soulignement est en fait une variable shell spéciale. Ce que vous voyez ici est la _variable underscore ( ) avec une valeur de var=99. Il est en lecture seule et maintenu par le shell. C'est:

  • Défini au démarrage du shell, contenant le nom de fichier absolu du shell ou du script en cours d'exécution tel que transmis dans la liste des arguments.
  • Après cela, il se développe jusqu'au dernier argument de la commande précédente, après expansion.
  • Lors de la vérification du courrier, ce paramètre contient le nom du fichier courrier.
  • Il est également défini sur le chemin d'accès complet de chaque commande exécutée et placé dans l'environnement exporté vers cette commande.

Votre exemple tombe dans la deuxième catégorie. Vous avez tapé:

set -a var=99  

Donc, le dernier argument était var=99, et c'était la valeur que vous définissiez (vous n'étiez pas réglé varsur 99). Par conséquent, a _été fixé à cela. Et c'est ce qui est rapporté:

_=var=99  

C'est un peu déroutant, mais le premier =indique l'affectation à la variable _et le second fait partie de la valeur.

Il convient également de mentionner que l' -aoption to setentraînera l' exportation de toutes les variables définies ultérieurement .

Bob Eager
la source
16

La bonne réponse dépend du shell que vous utilisez:

  • pour bash, tout ce que @BobEager a dit s'applique
  • car zsh, il est uniquement défini sur le dernier argument de la commande précédente et sur le chemin d'accès complet de la commande dans l'environnement de la commande
  • certains shells aiment dashuniquement définir cette variable lors de l'exécution d'une session interactive

Il peut également y avoir d'autres particularités dans d'autres coquilles. En tant que tel, $_n'est pas défini dans POSIX, il faut donc être conscient des problèmes potentiels de portabilité lors de son utilisation.

Note latérale: si votre intention est d'attribuer la valeur de 99 à varet de la rendre disponible dans l'environnement des sous-processus suivants, la syntaxe correcte pour y parvenir est:

export var=99
Dmitry Grigoryev
la source
2
Une syntaxe également correcte est unset var;set -a; var=99. Fonctionne dans tous les shells résonnables (pas csh et al).
Flèche
1
@Arrow Bien que , selon la dernière ligne de Bob Eager répondre cela rendrait toutes les variables ultérieurement définies / modifiées exportées, qui peuvent ne pas être ce que vous voulez.
TripeHound
8

Et je note echo $varne donnera rien. … Que se passe-t'il?

Dans l'impression pas si fine de bash (1) , on trouve

set[ --abefhkmnptuvxBCEHPT] [ nom-option ] [ arg …]   [ ] [ nom-option ] [ arg …]-o
set+abefhkmnptuvxBCEHPT+o

            ︙
    Lorsque des options sont spécifiées, elles définissent ou désactivent les attributs du shell. Tous les arguments restant après le traitement des options sont traitées sous forme de valeurs pour les paramètres de position et sont affectés, dans l' ordre, à $1, $2, ... .$n

Ce qui signifie, set -a var=99ne définit pas la variable d'environnement varsur 99; il se met $1à var=99. Essayez echo "$1"ou echo "$*"et vous verrez.

Scott
la source