Qual é o último argumento do comando anterior?

11

$_ é considerado o último argumento do comando anterior.

Então, pergunto-me por que não é EDITOR="emacs -nw" mas EDITOR no exemplo a seguir?

Por que "emacs -nw" não é parte do último argumento?

Mais geralmente, quais são as definições de um argumento e o último argumento?

Obrigado.

$ export EDITOR="emacs -nw"
$ echo $_
EDITOR
    
por Tim 12.04.2018 / 13:39

3 respostas

13

O Bash processa atribuições de variáveis, quando elas são permitidas como argumentos (com alias , declare , export , local , readonly e typeset ), antes de mais nada (ou melhor, ele os identifica antes de mais nada - a expansão se aplica aos valores atribuídos às variáveis). Quando chegar à expansão de palavras, o comando restante é export EDITOR , então _ é definido como EDITOR .

De um modo geral, os argumentos são as "palavras" restantes após a expansão (que não inclui atribuições de variáveis e redirecionamentos).

Consulte Expansão simples do comando em o manual de Bash para detalhes.

    
por 12.04.2018 / 13:57
4

TL; DR: No caso de export FOO=bar , o bash invoca sua criação de ambiente temporário, define FOO=bar nesse ambiente e, em seguida, gera um comando final de export FOO . Nesse ponto, FOO é considerado o último argumento.

Ah, o muito abusado $_ :

($_, an underscore.) 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. Subsequently, expands to the last argument to the previous command, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file.

Vamos ver algumas variações:

$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_

echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_

$ export MANPATH=/tmp; echo $_
MANPATH

Então, vemos três padrões aqui:

  • Comandos invocados a partir do sistema de arquivos, funções e built-ins se comportam como geralmente esperado: $_ é configurado para o nome do comando se nenhum argumento, caso contrário, o último dos argumentos apresentados.
  • Após definições de funções, loops e outras construções lógicas: $_ não é modificado.
  • Todo o resto: $_ está definido para algo não esperado; estranho.

Eu já instrumentei o código para fornecer algumas dicas sobre a estranheza.

$ ./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$ ./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$ ./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]

Você pode ver que o analisador vê o último argumento esperado ( lastarg= ) em todos os casos, mas o que acontece depois disso depende do que o bash acha que deve acontecer. Veja execute_cmd.c, execute_simple_command () .

No caso de export FOO=bar , bash faz a atribuição e, em seguida, exporta a variável. Isso parece consistente com a afirmação da documentação de que o último argumento foi calculado após a expansão.

    
por 12.04.2018 / 18:37
2

Para responder à pergunta do título, tente !$ :

$ export EDITOR="emacs -nw"
$ echo !$
EDITOR=emacs -nw

Esta é a expansão do histórico. A partir da manch bash:

History expansion is performed immediately after a complete line is read, before the shell breaks it into words. It takes place in two parts. The first is to determine which line from the history list to use during substitution. The second is to select portions of that line for inclusion into the current one. The line selected from the history is the event, and the portions of that line that are acted upon are words.

...

Event Designators

...

! Start a history substitution, except when followed by a blank, newline, carriage return, = or ( (when the extglob shell option is enabled using the shopt builtin).

...

!! Refer to the previous command. This is a synonym for '!-1'.

...

Word Designators

...

$ The last word. This is usually the last argument, but will expand to the zeroth word if there is only one word in the line.

...

If a word designator is supplied without an event specification, the previous command is used as the event.

    
por 12.04.2018 / 17:20

Tags