Comprendi il significato di `$ _`


12

Potresti spiegare le seguenti frasi del manuale di Bash $_, in particolare le parti in grassetto, forse con alcuni esempi?

  1. All'avvio della shell, impostare il percorso assoluto utilizzato per richiamare la shell o lo script della shell in esecuzione come passato nell'ambiente o nell'elenco degli argomenti .

  2. Successivamente , si espande all'ultimo argomento al comando precedente, dopo l'espansione.

  3. Impostato anche sul nome percorso completo utilizzato per richiamare ciascun comando eseguito e inserito nell'ambiente esportato in quel comando .

  4. Quando si controlla la posta , questo parametro contiene il nome del file di posta.


4
-1 domanda poco chiara e non approfondita. Che cosa hai provato? Dove sono state le tue aspettative in disallineamento con il testo? Non capisci onestamente la parola "successivamente"? Se un nuovo utente dovesse porre questa stessa domanda, avrei le stesse domande (nonostante la mia innata curiosità simile a come esattamente funzionano le cose).
Jeff Schaller

Risposte:


20

Sono d'accordo non è molto chiaro.

1. All'avvio della shell,

  • se la _variabile si trovava nell'ambiente che ha bashricevuto , la bashlascia intatta.

    In particolare, se quella bashshell è stata invocata da un'altra bash shell (sebbene zsh, yashe alcune kshimplementazioni lo fanno anche), allora quella bashshell avrà impostato la _variabile d'ambiente sul percorso del comando in esecuzione (che è il 3 ° punto nella tua domanda). Ad esempio, se bashviene invocato per interpretare uno script come risultato di un'altra bashinterpretazione della shell:

    bash-script some args

    Quello bashsarà passato _=/path/to/bash-scripnell'ambiente dato a bash-script, ed è quello che sarà il valore iniziale della $_ bashvariabile nella bashshell che interpreta quello script.

    $ env -i _=whatever bash -c 'echo "$_"'
    whatever
    
  • Ora, se l'applicazione che invoca non passa una _variabile d'ambiente , la bashshell invocata si inizializzerà $_a quella argv[0]che riceve se stessa che potrebbe essere bash, /path/to/basho /path/to/some-scripto qualsiasi altra cosa (nell'esempio sopra, sarebbe /bin/bashse lo sballo dello script era #! /bin/bash o a /path/to/bash-script seconda del sistema ).

    Quindi quel testo è fuorviante in quanto descrive il comportamento del chiamante che bashnon ha alcun controllo. L'applicazione che ha invocato bashpotrebbe benissimo non essere impostata $_affatto (in pratica, solo alcune shell e alcune rare applicazioni interattive lo fanno, execlp()non per esempio), oppure potrebbe usarla per qualcosa di completamente diverso (per esempio ksh93imposta su *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. Successivamente

Il successivo non è neanche molto chiaro. In pratica, questo non appena bashinterpreta un semplice comando nell'attuale ambiente shell.

  • Nel caso di una shell interattiva , sarà il primo semplice comando interpretato /etc/bash.bashrcad esempio.

    Ad esempio, al prompt di una shell interattiva:

     $ 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
    
  • Per una shell non interattiva , sarebbe il primo comando nel $BASH_ENVo del codice inviato a quella shell se $BASH_ENVnon è impostato.

3. Quando Bash esegue un comando

Il terzo punto è qualcosa di diverso ed è accennato nella discussione sopra.

bash, come poche altre shell passerà una _variabile di ambiente ai comandi che esegue che contiene il percorso bashutilizzato come primo argomento per le execve()chiamate di sistema.

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

4. Quando si controlla la posta

Il quarto punto è descritto in maggior dettaglio nella descrizione della MAILPATHvariabile:

'MAILPATH'

Un elenco separato da due punti di nomi di file che la shell verifica periodicamente per la nuova posta .

Ogni voce dell'elenco può specificare il messaggio che viene stampato quando arriva una nuova posta nel file di posta separando il nome del file dal messaggio con un '?'. Se utilizzato nel testo del messaggio, '$ _' si espande nel nome del file di posta corrente.

Esempio:

$ MAILCHECK=1 MAILPATH='/tmp/a?New mail in <$_>' bash
bash$ echo test >> /tmp/a
New mail in </tmp/a>

4

Prova questo semplice esempio:

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

Eseguilo dando il percorso assoluto ( /home/$USERNAME/test.sh); produzione:

/home/$USERNAME/test.sh
test
test

Il primo $_contiene il percorso che hai usato per invocare lo script e il secondo contiene il primo argomento al centro echo. Per il terzo elemento nell'elenco, se si avvia un nuovo terminale e si digita echo $_ , verrà mostrata la variabile contenente quella PATHche viene solitamente utilizzata per cercare e invocare i comandi (nella mia macchina Ubuntu) in una shell normale o percorso assoluto del .bashrsfile in una shell di login.

Per l'articolo quattro dalla pagina man di bash:

Se utilizzato nel testo del messaggio, si $_espande nel nome del file di posta corrente.


Grazie. (1) puoi spiegare il terzo caso con esempi? (2) Quando apro una nuova scheda terminale di gnome, l'output di echo $_è EDITOR, e perché? Quale caso segue? (3) Puoi darci un esempio di come controllare la posta e di come utilizzarla $_in questo caso?
Tim

Apri il tuo .bashrce commenta ogni riga lì. Mantieni solo una riga contenente un comando simile echo "test"o simile. Salva e chiudi. Quindi corri bashe immediatamente echo $_. Quest'ultima eco dovrebbe stampare il test nell'output.
coffeMug

Per la parte della posta non ho usato la posta Unix e non ho una posta funzionante installata sul mio sistema, quindi non posso darvi un esempio. Ma dovrebbe essere ovvio se segui la descrizione di MAILPATHin linuxcommand.org/lc3_man_pages/bash1.html
coffeMug

1
Cordiali saluti, la versione canonica e aggiornata del manuale di bash è: gnu.org/software/bash/manual/bashref.html . È la versione 4.3 mentre la pagina dei comandi linux era 4.1.
Jeff Schaller

1

Per il caso 2, un esempio vale più di mille parole:

mkdir my_long_dir
cd $_

Fa quello che indovineresti / speri. Mi dà un semplice segnaposto quando sono sulla riga di comando per salvarmi dal ripetermi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.