Comprendre la signification de «$ _»

12

Pourriez-vous expliquer les phrases suivantes du manuel de Bash $_, en particulier les parties en gras, peut-être avec quelques exemples?

  1. Au démarrage du shell, définissez le chemin d'accès absolu utilisé pour appeler le shell ou le script de shell en cours d'exécution tel que transmis dans l'environnement ou la liste d'arguments .

  2. Par la suite , se développe jusqu'au dernier argument de la commande précédente, après expansion.

  3. Définissez également le chemin d'accès complet utilisé pour appeler chaque commande exécutée et placée dans l'environnement exporté vers cette commande .

  4. Lors de la vérification du courrier , ce paramètre contient le nom du fichier courrier.

Tim
la source
4
-1 question peu claire et pas complètement étudiée. Qu'as-tu essayé? Où vos attentes ne correspondaient-elles pas au texte? Ne comprenez-vous pas honnêtement le mot «ultérieurement»? Si un nouvel utilisateur posait la même question, je lui poserais les mêmes questions (malgré ma curiosité innée similaire quant à la façon exacte dont les choses fonctionnent).
Jeff Schaller

Réponses:

20

Je suis d'accord, ce n'est pas très clair.

1. Au démarrage du shell,

  • si la _variable était dans l'environnement qui a bashreçu , puis la bashlaisse intacte.

    En particulier, si ce bashshell a été invoqué par un autre bash shell (cependant zsh, yashet certaines kshimplémentations le font également), alors ce bashshell aura défini la _variable d'environnement sur le chemin de la commande en cours d'exécution (c'est le 3ème point de votre question). Par exemple, si bashest invoqué pour interpréter un script à la suite d'une autre bashinterprétation du shell:

    bash-script some args

    Cela bashsera passé _=/path/to/bash-scripdans l'environnement donné à bash-script, et c'est à cela que la valeur initiale de la $_ bashvariable sera dans le bashshell qui interprète ce script.

    $ env -i _=whatever bash -c 'echo "$_"'
    whatever
  • Maintenant, si l'application appelante ne transmet pas de _variable d'environnement , le bashshell invoqué s'initialisera $_à ce argv[0]qu'il reçoit lui-même, ce qui pourrait être bash, ou /path/to/bashou /path/to/some-scriptou autre chose (dans l'exemple ci-dessus, ce serait le /bin/bashcas si le coup du script était #! /bin/bash ou /path/to/bash-script selon le système ).

    Ce texte est donc trompeur car il décrit le comportement de l'appelant qui bashn'a aucun contrôle sur. L'application invoquée bashpeut très bien ne pas être définie $_du tout (en pratique, seuls certains shells et quelques rares applications interactives le font, execlp()par exemple), ou elle pourrait l'utiliser pour quelque chose de complètement différent (par exemple, la ksh93définit sur *pid*/path/to/command).

    $ env bash -c 'echo "$_"'
    /usr/bin/env   (env did not set it to /bin/bash, so the value we
                   get is the one passed to env by my interactive shell)
    $ ksh93 -c 'bash -c "echo \$_"'
    *20042*/bin/bash

2. Par la suite

La suite n'est pas très claire non plus. En pratique, c'est dès que l'on bashinterprète une simple commande dans l'environnement shell actuel.

  • Dans le cas d'un shell interactif , ce sera sur la première commande simple interprétée /etc/bash.bashrcpar exemple.

    Par exemple, à l'invite d'un shell interactif:

     $ echo "$_"
     ]      (the last arg of the last command from my ~/.bashrc)
     $ f() { echo test; }
     $ echo "$_"
     ]      (the command-line before had no simple command, so we get
             the last argument of that previous echo commandline)
     $ (: test)
     $ echo "$_"
     ]      (simple command, but in a sub-shell environment)
     $ : test
     $ echo "$_"
     test
  • Pour un shell non interactif , ce serait la première commande dans $BASH_ENVou du code fourni à ce shell s'il $BASH_ENVn'est pas défini.

3. Lorsque Bash exécute une commande

Le troisième point est quelque chose de différent et est indiqué dans la discussion ci-dessus.

bash, comme quelques autres shells transmettront une _variable d'environnement aux commandes qu'il exécute qui contient le chemin bashutilisé comme premier argument des execve()appels système.

$ env | grep '^_'
_=/usr/bin/env

4. Lors de la vérification du courrier

Le quatrième point est décrit plus en détail dans la description de la MAILPATHvariable:

«MAILPATH»

Une liste de noms de fichiers séparés par deux-points que le shell vérifie périodiquement pour les nouveaux messages .

Chaque entrée de liste peut spécifier le message qui est imprimé lorsque de nouveaux messages arrivent dans le fichier courrier en séparant le nom de fichier du message par un «?». Lorsqu'il est utilisé dans le texte du message, «$ _» se développe jusqu'au nom du fichier courrier actuel.

Exemple:

$ MAILCHECK=1 MAILPATH='/tmp/a?New mail in <$_>' bash
bash$ echo test >> /tmp/a
New mail in </tmp/a>
Stéphane Chazelas
la source
4

Essayez cet exemple simple:

echo "$_"
echo "test"
echo "$_"

Exécutez-le en donnant le chemin absolu ( /home/$USERNAME/test.sh); production:

/home/$USERNAME/test.sh
test
test

Le premier $_contient le chemin que vous avez utilisé pour appeler le script et le second contient le premier argument au milieu echo. Pour le troisième élément de la liste, si vous démarrez un nouveau terminal et tapez echo, $_ il affichera la variable contenant le PATHqui est généralement utilisé pour rechercher et appeler des commandes (dans ma machine Ubuntu) dans un shell normal ou un chemin absolu vers votre .bashrsfichier dans un shell de connexion.

Pour l'élément quatre de la page de manuel bash:

Lorsqu'il est utilisé dans le texte du message, se $_développe jusqu'au nom du fichier courrier en cours.

coffeMug
la source
Merci. (1) pouvez-vous expliquer le troisième cas avec des exemples? (2) Lorsque j'ouvre un nouvel onglet de terminal gnome, la sortie de echo $_est EDITOR, et pourquoi? Quel cas suit-il? (3) Pouvez-vous donner un exemple de la façon de vérifier les courriers et de les utiliser $_dans ce cas?
Tim
Ouvrez votre .bashrcet commentez chaque ligne là-bas. Conservez une seule ligne contenant une commande similaire echo "test"ou similaire. Sauver et fermer. Ensuite, exécutez bashet immédiatement echo $_. Ce dernier écho devrait imprimer test dans la sortie.
coffeMug
Pour la partie courrier, je n'ai pas utilisé de courrier Unix et je n'ai pas de courrier de travail installé sur mon système, je ne peux donc pas vous donner d'exemple. Mais cela devrait être évident si vous suivez la description de MAILPATHdans linuxcommand.org/lc3_man_pages/bash1.html
coffeMug
1
Pour info, la version canonique et à jour du manuel bash est: gnu.org/software/bash/manual/bashref.html . C'est la version 4.3 alors que la page linuxcommand était 4.1.
Jeff Schaller
1

Pour le cas 2, un exemple vaut mille mots:

mkdir my_long_dir
cd $_

Fait ce que vous devinez / espérez. Me donne un espace réservé simple lorsque je suis sur la ligne de commande pour éviter de me répéter.

dsz
la source