Entenda o significado de '$ _'

6

Você poderia explicar as seguintes frases do manual do Bash sobre $_ , especialmente as partes em negrito, talvez com alguns exemplos?

  1. At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list.

  2. Subsequently, expands to the last argument to the previous command, after expansion.

  3. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command.

  4. When checking mail, this parameter holds the name of the mail file.

por Tim 01.05.2016 / 22:52

2 respostas

14

Concordo que não está muito claro.

1. Na inicialização do shell,

  • se a variável _ estiver no ambiente em que bash recebeu , então bash não será afetada.

    Em particular, se esse bash shell foi invocado por outro bash shell (embora as implementações zsh , yash e algumas ksh também façam ), então, bash shell terá definido o ambiente _ variável para o caminho do comando que está sendo executado (que é o terceiro ponto em sua pergunta). Por exemplo, se bash for invocado para interpretar um script como resultado de outra interpretação de bash shell:

    bash-script some args
    

    Esse bash terá passado _=/path/to/bash-scrip no ambiente dado a bash-script , e é isso que a inicial O valor da variável $_ bash estará no shell bash que interpreta esse script.

    $ env -i _=whatever bash -c 'echo "$_"'
    whatever
    
  • Agora, se o aplicativo chamado não passar um ambiente _ variável , o shell bash invocado inicializará $_ para o argv[0] que receber próprio que poderia ser bash ou /path/to/bash ou /path/to/some-script ou qualquer outra coisa (no exemplo acima, isso seria /bin/bash se a explosão do script fosse #! /bin/bash ou /path/to/bash-script dependendo do sistema ).

    Para que o texto seja enganoso, pois descreve o comportamento do chamador no qual bash não tem controle. O aplicativo que invocou bash pode muito bem não definir $_ (na prática, apenas alguns shells e algumas raras aplicações interativas, execlp() não por exemplo), ou poderia usá-lo para algo completamente diferente (por exemplo, ksh93 define como *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. Posteriormente

O Subsequentemente também não é muito claro. Na prática, isso é assim que bash interpreta um comando simples no ambiente atual do shell.

  • No caso de um shell interativo , isso estará no primeiro comando simples interpretado a partir de /etc/bash.bashrc , por exemplo.

    Por exemplo, no prompt de um shell interativo:

     $ 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
    
  • Para um shell não interativo , seria o primeiro comando em $BASH_ENV ou do código alimentado para esse shell se $BASH_ENV não fosse conjunto.

3. Quando o Bash executa um comando

O terceiro ponto é algo diferente e é sugerido na discussão acima.

bash , como alguns outros shells passarão uma variável de ambiente _ para comandos que executam que contém o caminho que bash usou como o primeiro argumento para as chamadas do sistema execve() .

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

4. Ao verificar o correio

O quarto ponto é descrito com mais detalhes na descrição da variável MAILPATH :

'MAILPATH'

A colon-separated list of filenames which the shell periodically checks for new mail.

Each list entry can specify the message that is printed when new mail arrives in the mail file by separating the filename from the message with a '?'. When used in the text of the message, '$_' expands to the name of the current mail file.

Exemplo:

$ MAILCHECK=1 MAILPATH='/tmp/a?New mail in <$_>' bash
bash$ echo test >> /tmp/a
New mail in </tmp/a>
    
por 02.05.2016 / 13:24
4

Tente este exemplo simples:

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

Execute-o dando o caminho absoluto ( /home/$USERNAME/test.sh ); saída:

/home/$USERNAME/test.sh
test
test

Primeiro $_ contém o caminho que você usou para invocar o script e o segundo contém o primeiro argumento para o meio echo . Para o terceiro item da lista, se você iniciar um novo terminal e digitar echo $_ mostrará a variável contendo o PATH que é normalmente usado para procurar e invocar comandos (em minha máquina Ubuntu) em um shell normal ou caminho absoluto para o seu arquivo .bashrs em um shell de login.

Para o item quatro da página man do bash:

When used in the text of the message, $_ expands to the name of the current mailfile.

    
por 01.05.2016 / 22:57

Tags