¿Cuándo es `_` una variable de entorno de un shell bash?

10

Bash Manual dice (página de manual, mi énfasis):

Cuando Bash invoca un comando externo, la variable $_se establece en la ruta completa del comando y se pasa a ese comando en su entorno.

Y ( Parámetros especiales ):

_

( $_, un guión bajo). Al iniciar el shell, establezca el nombre de ruta absoluto utilizado para invocar el shell o el script de shell que se ejecuta como se pasa en el entorno o la lista de argumentos. Posteriormente, se expande hasta el último argumento del comando anterior, después de la expansión. Establezca también el nombre de ruta completo utilizado para invocar cada comando ejecutado y colocado en el entorno exportado a ese comando. Al verificar el correo, este parámetro contiene el nombre del archivo de correo.

  1. En un bash shell, ejecuto:

    $ bash
    $ export | grep '_=' 

    Según el manual, _debería ser una variable de entorno del nuevo shell bash. exportse supone que genera todas las variables de entorno del nuevo bash shell, pero no genera _. Entonces, me pregunto si _es una variable de entorno del nuevo bash shell.

  2. En realidad, en cualquier shell de bash, sucede lo mismo

    $ export | grep '_='

    no da salida a nada. Entonces, me pregunto si _alguna vez es una variable de entorno de un shell bash.

  3. Para comparacion:

    $ dash
    $ export  | grep '_='        
    export _='/bin/dash'

Mi publicación está inspirada en el comentario de Mike y la respuesta de Stephane .

Tim
fuente
1
Es una variable de shell y se pasa al entorno del comando ; no se exporta necesariamente al entorno del shell . exportes incorporado, pero si lo usa printenv _, le mostrará cómo se invocó: /usr/bin/printenven este sistema.
Toby Speight
Tenga en cuenta que bash -c export | grep _=(de golpe), se mostrará cómo el shell padre invoca el bashcomando, a pesar de que $_no está definida en la matriz.
Toby Speight
Consulte también unix.stackexchange.com/questions/293302 .
JdeBP

Respuestas:

13

Sí, _es una variable de entorno del nuevo shell Bash; puedes ver eso corriendo

tr '\0' '\n' < /proc/$$/environ | grep _=

dentro del shell: que muestra el contenido del entorno inicial del shell. No lo verá en el primer shell porque no había un shell anterior para configurarlo antes de que comenzara.

Expandir $_dentro de Bash se refiere al _parámetro especial, que se expande al último argumento del comando anterior. (Internamente, Bash maneja esto mediante el uso de una _variable de shell, que se actualiza cada vez que se analiza un comando, pero eso es realmente un detalle de implementación. Es "no exportado" cada vez que se analiza un comando ) .export No se muestra _porque no es una variable que se marca como exportada; Sin embargo, puede verlo en la salida de set.

En el primer ejemplo, el nuevo shell Bash analiza y ejecuta los comandos en sus archivos de inicio, por lo que, cuando se ejecuta explore | grep '-=', _ya se ha sobrescrito y marcado como no exportado.

En el dashejemplo, no parece ejecutar ningún archivo de inicio, por lo que está viendo la variable como una variable de entorno establecida por Bash antes de ejecutarse dash.

Stephen Kitt
fuente
Gracias. En el nuevo bash shell, ¿por qué no export | grep '_='muestra nada? En el shell bash original, ¿por qué no tr '\0' '\n' < /proc/$$/environ | grep _=muestra nada?
Tim
9

exportsin argumentos enumera todas las variables exportadas . _no es una variable, pero aparece como un parámetro especial .

Algo confuso, _también sería un nombre válido para una variable , a diferencia de los nombres de los otros parámetros especiales. Al menos Bash 4.4 permite tareas, sin quejas. Simplemente no es útil porque el efecto especial anula inmediatamente el valor.

ilkkachu
fuente
2
Sin _embargo, diviértete intentando usarlo como variable ;-). Efectivamente es de solo escritura y el valor se pierde de inmediato.
Stephen Kitt
1
Además, internamente Bash trata _como una variable, por lo que aparece en la salida de set. Sin embargo, no se puede marcar como exportado hasta donde puedo determinar.
Stephen Kitt
2
@StephenKitt, pero Bash 4.4 permite marcarlo como de solo lectura. O un entero. Con resultados algo divertidos.
ilkkachu
1
Ja, bonito descubrimiento, ¡eso es bastante divertido!
Stephen Kitt
5

No todas las variables de shell están marcadas como exportadas, como puede ver en la salida de declare -p.

No tiene ningún sentido bashmarcar $_como exportado porque agrega automáticamente esta variable al entorno de los procesos secundarios pero con un valor diferente al que tiene en el shell (en ese momento).

Mostrarlo como exportado confundiría al usuario sobre lo que sucederá con el entorno de los comandos externos.

Todas las "variables de tiempo de ejecución" BASH*no se exportan.

Hauke ​​Laging
fuente