Comprender el significado de `$ _`

12

¿Podría explicar las siguientes oraciones del manual de Bash sobre $_, especialmente las partes en negrita, tal vez con algunos ejemplos?

  1. 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 .

  2. Posteriormente , se expande hasta el último argumento del comando anterior, después de la expansión.

  3. Establezca también el nombre de ruta completo utilizado para invocar cada comando ejecutado y colocado en el entorno exportado a ese comando .

  4. Al verificar el correo , este parámetro contiene el nombre del archivo de correo.

Tim
fuente
44
-1 pregunta poco clara y no investigada a fondo. Que has intentado ¿Dónde se alinearon tus expectativas con el texto? ¿No entiendes honestamente la palabra "posteriormente"? Si un nuevo usuario hiciera esta misma pregunta, tendría las mismas preguntas (a pesar de mi curiosidad innata similar en cuanto a cómo funcionan exactamente las cosas).
Jeff Schaller

Respuestas:

20

Estoy de acuerdo, no está muy claro.

1. Al iniciar el shell,

  • si la _variable estaba en el entorno que la bashrecibió , la bashdeja intacta.

    En particular, si ese bashshell fue invocado por otro bash shell (sin embargo zsh, yashy algunas kshimplementaciones también lo hacen), entonces ese bashshell habrá establecido la _variable de entorno en la ruta del comando que se está ejecutando (ese es el tercer punto en su pregunta). Por ejemplo, si bashse invoca para interpretar un script como resultado de otra bashinterpretación de shell:

    bash-script some args

    Eso bashhabrá pasado _=/path/to/bash-scripen el entorno dado bash-script, y ese es el valor inicial de la $_ bashvariable en el bashshell que interpreta ese script.

    $ env -i _=whatever bash -c 'echo "$_"'
    whatever
    
  • Ahora, si la aplicación que invoca no pasa una _variable de entorno , el bashshell invocado se inicializará $_en el que argv[0]se recibe, que podría ser bash, /path/to/basho /path/to/some-scripto cualquier otra cosa (en el ejemplo anterior, eso sería /bin/bashsi el she-bang del script era #! /bin/bash o /path/to/bash-script dependiendo del sistema ).

    De modo que el texto es engañoso ya que describe el comportamiento de la persona que llama que bashno tiene control. Es bashmuy posible que la aplicación que se invocó no se configure $_en absoluto (en la práctica, solo algunos shells y algunas aplicaciones interactivas raras lo hacen, execlp()por ejemplo), o podría usarlo para algo completamente diferente (por ejemplo, ksh93configurarlo *pid*/path/to/command).

    $ env bash -c 'echo "$_"'
    /usr/bin/env   (env did not set it to /bin/bash, so the value we
                   get is the one passed to env by my interactive shell)
    $ ksh93 -c 'bash -c "echo \$_"'
    *20042*/bin/bash
    

2. Posteriormente

El Posteriormente no está muy claro tampoco. En la práctica, eso es tan pronto como bashinterpreta un comando simple en el entorno de shell actual.

  • En el caso de un shell interactivo , eso estará en el primer comando simple interpretado, /etc/bash.bashrcpor ejemplo.

    Por ejemplo, en el indicador de un shell interactivo:

     $ echo "$_"
     ]      (the last arg of the last command from my ~/.bashrc)
     $ f() { echo test; }
     $ echo "$_"
     ]      (the command-line before had no simple command, so we get
             the last argument of that previous echo commandline)
     $ (: test)
     $ echo "$_"
     ]      (simple command, but in a sub-shell environment)
     $ : test
     $ echo "$_"
     test
    
  • Para un shell no interactivo , sería el primer comando en $BASH_ENVo del código alimentado a ese shell si $BASH_ENVno está configurado.

3. Cuando Bash ejecuta un comando

El tercer punto es algo diferente y se insinúa en la discusión anterior.

bash, como algunos otros shells pasarán una _variable de entorno a los comandos que ejecuta que contiene la ruta que se bashutilizó como primer argumento para las execve()llamadas al sistema.

$ env | grep '^_'
_=/usr/bin/env

4. Al revisar el correo

El cuarto punto se describe con más detalles en la descripción de la MAILPATHvariable:

'MAILPATH'

Una lista de nombres de archivos separados por dos puntos que el shell comprueba periódicamente si hay correo nuevo .

Cada entrada de la lista puede especificar el mensaje que se imprime cuando llega un nuevo correo en el archivo de correo separando el nombre del archivo del mensaje con un '?'. Cuando se usa en el texto del mensaje, '$ _' se expande al nombre del archivo de correo actual.

Ejemplo:

$ MAILCHECK=1 MAILPATH='/tmp/a?New mail in <$_>' bash
bash$ echo test >> /tmp/a
New mail in </tmp/a>
Stéphane Chazelas
fuente
4

Prueba este sencillo ejemplo:

echo "$_"
echo "test"
echo "$_"

Ejecútelo dando la ruta absoluta ( /home/$USERNAME/test.sh); salida:

/home/$USERNAME/test.sh
test
test

Primero $_contiene la ruta que usó para invocar el script y el segundo contiene el primer argumento en el medio echo. Para el tercer elemento de la lista, si inicia una nueva terminal y escribe echo $_ , mostrará la variable que contiene la PATHque generalmente se usa para buscar e invocar comandos (en mi máquina Ubuntu) en un shell normal o ruta absoluta a su .bashrsarchivo en un shell de inicio de sesión.

Para el elemento cuatro de la página de manual de bash:

Cuando se usa en el texto del mensaje, se $_expande al nombre del archivo de correo actual.

taza de cafe
fuente
Gracias. (1) ¿puedes explicar el tercer caso con ejemplos? (2) Cuando abro una nueva pestaña de terminal gnome, la salida de echo $_es EDITOR, y ¿por qué es? ¿Qué caso sigue? (3) ¿Puede dar un ejemplo de cómo verificar los correos electrónicos y cómo usarlos $_en este caso?
Tim
Abre tu .bashrcy comenta cada línea allí. Mantenga solo una línea que contenga un comando similar echo "test"o similar. Guardar y cerrar. Luego corre bashe inmediatamente echo $_. Este último eco debería imprimir la prueba en la salida.
coffeMug
Para la parte de correo, no he usado el correo de Unix y no tengo un correo de trabajo instalado en mi sistema ahora, así que no puedo darles un ejemplo. Pero debería ser obvio si sigue la descripción de MAILPATHen linuxcommand.org/lc3_man_pages/bash1.html
coffeMug
1
Para su información, la versión canónica y actualizada del manual de bash es: gnu.org/software/bash/manual/bashref.html . Es la versión 4.3 mientras que la página de linuxcommand era 4.1.
Jeff Schaller
1

Para el caso 2, un ejemplo vale más que mil palabras:

mkdir my_long_dir
cd $_

Hace lo que adivina / espera. Me da un marcador de posición simple cuando estoy en la línea de comando para evitar que tenga que repetirme.

dsz
fuente