Qual é o significado de "_ ="?

29

Depois de executar o set -a var=99, posso encontrar uma frase na saída de set:

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

Alguém poderia me dizer o que "_ =" significa?

Noto que echo $varnão dará nada. Se eu executar o set -a, o setnão incluirá essa variável novamente. O que está acontecendo?

yode
fonte

Respostas:

16

Quando você executa set -a var=99, três coisas distintas acontecem (relacionadas à sua pergunta):

  1. Uma opção definida ( -a) (inverter fazendo set +a) para exportar vars.
  2. Os parâmetros posicionais são "definidos" para o que segue as opções ( $1definido como var=99).
  3. O sublinhado da variável shell $_é definido como o último parâmetro (expandido).

defina -a

A execução de set -amarca todas as variáveis ​​subsequentes (novas ou alteradas) como exportadas (em todos os shells, exceto em cshalguns shells relacionados).

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

Para se recuperar dessa configuração, basta alterar -para 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

set var = 99

O que deveria ser, na verdade, set -- var=99evitar a interpretação de uma opção (e o conjunto possui muito) com valores que começam com um hífen ( -).

Define a lista de argumentos (a lista de parâmetros posicionais) para aquela após o --. Isso é válido em todas as conchas razoáveis ​​(não em csh et al). Argumentos posicionais são impressos com "$ @" (ou semelhante "$ *", diferente de).

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

_ = last_argument

E, o valor da variável interna do shell _muda para o último argumento da linha executada. Isso NÃO é verdade em quase todos os shells (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh e, claro, csh e tcsh), exceto o 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

Observe que o valor em $_é o valor após a expansão:

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

$ echo "$_"
A New_Argument

É por isso que quando você executa:

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

Você obtém uma descrição da variável do shell '$ _'. Isso também funciona:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"
Seta
fonte
37

O sublinhado é na verdade uma variável de shell especial. O que você está vendo aqui é a _variável underscore ( ) com um valor de var=99. É somente leitura e mantido pelo shell. Isto é:

  • Defina na inicialização do shell, contendo o nome absoluto do arquivo do shell ou script sendo executado conforme passado na lista de argumentos.
  • Depois disso, ele se expande para o último argumento do comando anterior, após a expansão.
  • Ao verificar o correio, este parâmetro mantém o nome do arquivo de correio.
  • Também é definido como o nome do caminho completo de cada comando executado e colocado no ambiente exportado para esse comando.

Seu exemplo se enquadra na segunda categoria. Você digitou:

set -a var=99  

Assim, o último argumento não havia var=99, e que foi o valor que você foram definição (você não estavam montando vara 99). Por isso, _foi definido para isso. E é isso que está sendo relatado:

_=var=99  

É um pouco confuso, mas o primeiro =indica a atribuição à variável _e o segundo faz parte do valor.

Também vale ressaltar que a -aopção de setfazer com que todas as variáveis ​​definidas posteriormente sejam exportadas.

Bob Eager
fonte
16

A resposta certa dependeria do shell que você está usando:

  • pois bash, o que o @BobEager disse se aplica
  • pois zsh, é definido apenas para o último argumento do comando anterior e para o nome do caminho completo do comando no ambiente do comando
  • alguns shells, como dashapenas definem essa variável ao executar uma sessão interativa

Pode haver outras particularidades em outras conchas também. Como tal, não$_ está definido no POSIX, portanto, você deve estar ciente dos possíveis problemas de portabilidade ao usá-lo.

Nota lateral: se sua intenção é atribuir o valor de 99 vare disponibilizá-lo no ambiente de subprocessos subsequentes, a sintaxe correta para conseguir isso é:

export var=99
Dmitry Grigoryev
fonte
2
Uma sintaxe também correta é unset var;set -a; var=99. Funciona em todas as conchas ressonáveis ​​(não csh et al).
Arrow
1
@ Arrow Embora, de acordo com a última linha da resposta de Bob Eager, isso faça com que todas as variáveis ​​sejam definidas / modificadas posteriormente exportadas, o que pode não ser o que você deseja.
TripeHound 12/07/19
8

E notei echo $varque não dará nada. … O que aconteceu?

Na impressão não tão fina de bash (1) , encontramos

set[ --abefhkmnptuvxBCEHPT] [ nome da opção ] [ arg …]   [ ] [ nome da opção ] [ arg …]-o
set+abefhkmnptuvxBCEHPT+o

            Options
    Quando as opções são especificadas, elas definem ou desabilitam os atributos do shell. Quaisquer argumentos restantes após o processamento opção são tratados como valores para os parâmetros posicionais e são atribuídos, em ordem, para $1, $2... .$n

O que significa set -a var=99que não define a variável de ambiente varcomo 99; define $1como var=99. Tente echo "$1"ou echo "$*"e você verá.

Scott
fonte