Qual é o significado de “_ =”?

28

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?

Eu noto que echo $var não dará nada. Se eu executar o set -a , o set não incluirá essa variável novamente. O que está acontecendo?

    
por yode 11.07.2017 / 06:03

4 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 ( $1 definido como var=99 ).
  3. A variável shell underscore $_ está definida como o último parâmetro (expandido).

definir -a

A execução de set -a marca all variáveis subsequentes (novas ou alteradas) conforme exportadas (em todos os shells, exceto csh e algumas shells relacionadas).

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

Para recuperar-se dessa configuração, basta alterar o - para um + :

$ 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

conjunto var = 99

O que deve, na verdade, ser set -- var=99 para evitar a interpretação de uma opção (e o conjunto tem muito) com valores que começam com um traço ( - ).

Define a lista de argumentos (a lista de parâmetros posicionais) para isso após o -- . Isso é válido em todos os shells razoáveis (não em csh et al). Argumentos posicionais são impressos com "$ @" (ou similar "$ *", não igual).

$ 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 verdadeiro em quase todos os shells (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh e, claro, csh e tcsh) exceto 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

Por favor, note 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 de shell '$ _'. Isso também funciona:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"
    
por 11.07.2017 / 20:17
37

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

  • Defina na inicialização do shell, contendo o nome absoluto do arquivo do shell ou script que está sendo executado conforme transmitido na lista de argumentos.
  • Depois disso, ele é expandido para o último argumento para o comando anterior, após a expansão.
  • Ao verificar e-mail, esse parâmetro contém o nome do arquivo de mensagens.
  • Ele também é configurado para o nome completo do caminho de cada comando executado e colocado no ambiente exportado para esse comando.

Seu exemplo cai na segunda categoria. Você digitou:

set -a var=99  

Então o último argumento foi var=99 , e esse foi o valor que você estava definindo (você não estava definindo var para 99 ). Portanto, _ 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 a segunda faz parte do valor.

Também vale mencionar que a opção -a para set fará com que todas as variáveis definidas subseqüentemente sejam exportadas.

    
por 11.07.2017 / 06:18
16

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

  • para bash , seja o que for que o @BobEager disse aplicar
  • para zsh , está apenas definido para o último argumento do comando anterior e para o nome completo do caminho do comando no ambiente do comando
  • algumas conchas como dash definem essa variável somente ao executar uma sessão interativa

Pode haver outras particularidades em outras camadas também. Como tal, $_ é não definido no POSIX, portanto, deve-se estar ciente de potenciais problemas de portabilidade ao usá-lo.

Nota: se a sua intenção é atribuir o valor de 99 a var e disponibilizá-lo no ambiente de subprocessos subseqüentes, a sintaxe correta para isso é:

export var=99
    
por 11.07.2017 / 14:42
8

And I note echo $var will give nothing.  …  What’s happen?

Na impressão não muito boa de bash (1) , encontrar

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

            ︙
    When options are specified, they set or unset shell attributes.  Any arguments remaining after option processing are treated as values for the positional parameters and are assigned, in order, to $1, $2, … $n.

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

    
por 11.07.2017 / 08:39