¿Cuál es el significado de "_ ="?

29

Después de ejecutar el set -a var=99, puedo encontrar una oración en la salida de set:

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

¿Alguien podría decirme qué significa "_ ="?

Noto que echo $varno dará nada. Si ejecuto el set -a, entonces setno incluirá esta variable nuevamente. ¿Que esta pasando?

yode
fuente

Respuestas:

16

Cuando ejecuta set -a var=99, suceden tres cosas distintas (relacionadas con su pregunta):

  1. Una opción establecida ( -a) (revertir haciendo set +a) para exportar vars.
  2. Los parámetros posicionales se "configuran" según lo que sigue a las opciones (se $1configura como var=99).
  3. El guión bajo de la variable de shell $_se establece en el último parámetro (expandido).

conjunto -a

La ejecución de set -amarca todas las variables posteriores (nuevas o modificadas) como exportadas (en todos los shells, excepto en cshalgunos shells relacionados).

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

Para recuperarse de esta configuración, simplemente cambie -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

establecer var = 99

Lo que debería ser set -- var=99para evitar la interpretación de una opción (y el conjunto tiene mucho) con valores que comienzan con un guión ( -).

Establece la lista de argumentos (la lista de parámetros posicionales) a eso después de --. Eso es válido en todos los shells razonables (no en csh et al). Los argumentos posicionales se imprimen con "$ @" (o similar "$ *", no igual).

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

_ = último_argumento

Y, el valor de la variable de shell interna _cambia al último argumento de la línea ejecutada. Eso NO es cierto en casi todos los shells (jsh, ash, yash, dash, lksh, mksh, ksh93, attsh y, por supuesto, csh y tcsh) excepto 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

Tenga en cuenta que el valor en $_es el valor después de la expansión:

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

$ echo "$_"
A New_Argument

Es por eso que cuando ejecutas:

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

Obtiene una descripción de la variable de shell '$ _'. Esto también funciona:

$  set -a myvar=99; declare -p _
declare -- _="myvar=99"
Flecha
fuente
37

El guión bajo es en realidad una variable de shell especial. Lo que está viendo aquí es la _variable de subrayado ( ) con un valor de var=99. Es de solo lectura y lo mantiene el shell. Es:

  • Se establece en el inicio del shell, que contiene el nombre de archivo absoluto del shell o script que se ejecuta tal como se pasa en la lista de argumentos.
  • Después de eso, se expande al último argumento del comando anterior, después de la expansión.
  • Al verificar el correo, este parámetro contiene el nombre del archivo de correo.
  • También se establece en la ruta completa de cada comando ejecutado y colocado en el entorno exportado a ese comando.

Su ejemplo cae en la segunda categoría. Escribiste:

set -a var=99  

Por lo que el último argumento no había var=99, y que fue el valor que fueron escenario (no se estaban preparando vara 99). Por lo tanto, _se estableció en eso. Y eso es lo que se informa:

_=var=99  

Es un poco confuso, pero el primero =indica la asignación a la variable_ y el segundo es parte del valor.

También vale la pena mencionar que la -aopción sethará que todas las variables definidas posteriormente se exporten.

Bob ansioso
fuente
16

La respuesta correcta dependerá del shell que esté usando:

  • para bash, lo que sea que @BobEager dijo se aplica
  • para zsh, solo se establece en el último argumento del comando anterior y en la ruta completa del comando en el entorno del comando
  • algunos shells dashsolo establecen esta variable cuando se ejecuta una sesión interactiva

Puede haber otras particularidades en otros depósitos también. Como tal, no$_ está definido en POSIX, por lo que uno debe tener en cuenta los posibles problemas de portabilidad al usarlo.

Nota al margen: si su intención es asignar el valor de 99 vary ponerlo a disposición en el entorno de los subprocesos posteriores, la sintaxis correcta para lograr esto es:

export var=99
Dmitry Grigoryev
fuente
2
Una sintaxis también correcta es unset var;set -a; var=99. Funciona en todos los shells razonables (no csh et al).
Flecha
1
@Arrow Aunque de acuerdo con la última línea de la Eager Bob responde a esto haría que todas las variables establecidas posteriormente / modificados exportados, que pueden no ser lo que quieres.
TripeHound
8

Y noto echo $varque no dará nada. … ¿Que pasa?

En la letra no tan pequeña de bash (1) , encontramos

set[ --abefhkmnptuvxBCEHPT] [ nombre-opción ] [ arg ...]   [ ] [ nombre-opción ] [ arg ...]-o
set+abefhkmnptuvxBCEHPT+o

            ︙
    Cuando se especifican las opciones, establecen o desarman los atributos del shell. Cualquier argumento que quedan después de procesamiento de las opciones son tratados como valores para los parámetros de posición y se les asigna, en orden, a $1, $2, ... .$n

Lo que significa set -a var=99que no establece la variable de entorno varen 99; se pone $1a var=99. Prueba echo "$1"o echo "$*"y verás.

Scott
fuente