Comprensione del punto esclamativo (!) In bash


108

ero solito

history | less

per ottenere le righe dei comandi precedenti e dai numeri sul lato sinistro ho trovato la riga che volevo ripetere (es. 22) e ho fatto

!22

al prompt dei comandi e ha funzionato - eseguendo il set di comandi sulla linea che ho fatto in quel momento. Non riesco a capire dove viene utilizzato il punto esclamativo, cosa rappresenta in termini di azioni intraprese da bash e dove usarlo. Dalla documentazione non vedo una spiegazione "tangibile".


6
Questa risposta potrebbe essere d'aiuto
Michael Mrozek

9
Non una risposta alla tua domanda, ma <ctrl> + R ti consentirà di cercare in modo interattivo nella cronologia e quindi eseguire immediatamente se trovi quello che stavi cercando.
Kasterma,

Risposte:


144

!è una funzionalità che è apparso originariamente nella shell C , nei giorni precedenti prima che si potesse contare su terminali con tasti freccia. È particolarmente utile se aggiungi il numero del comando corrente al prompt ( PS1="\!$ ") in modo da poter guardare rapidamente lo schermo per ottenere numeri per i comandi precedenti.

Ora che puoi usare i tasti freccia e cose come Ctrl-Rcercare nella cronologia dei comandi, non vedo molto uso della funzione.

Una variante di ciò che potresti ancora trovare utile è !!, che esegue nuovamente il comando precedente. Da solo, non lo trovo !!Enterpiù veloce del semplice Enter, ma può essere utile se combinato in un comando più grande.

Esempio: un errore pilota comune nei sudosistemi basati è quello di dimenticare il sudoprefisso su un comando che richiede privilegi extra. Un principiante digita nuovamente l'intero comando. Lo studente diligente modifica il comando dalla cronologia dei comandi della shell. I tipi illuminati sudo !!.

Bash consente di disabilitare l' !elaborazione nella shell con set +o histexpando set +H. Puoi disabilitarlo in Zsh con set -K.


4
Trovo che Ctrl-P Ctrl-J sia piuttosto veloce; più veloce di Up Enter, almeno.
effimero

24
Se vuoi solo eseguire l'ultimo comando, Su / Invio va bene, ma se vuoi aggiungerlo in qualche modo (ad esempio, hai dimenticato sudoo qualcosa del genere), puoi farlo sudo !!, ad esempio. Potrebbe essere un po 'più veloce di "Su / Ctrl-A (o Home, se sei abbastanza fortunato) / sudo / spazio / invio". YMMV. :)

1
@AquariusPower: basta citarlo. O echo 'Hi!'oppure echo "Hi!"oppure echo Hi\!. Tutti fanno la stessa cosa.
Warren Young,

1
setopt NO_BANG_HISTin zsh potrebbe essere più memorabile di -K.
Gregory

48

Se non c'è una risposta più lunga qui ce n'è sicuramente una su Super User, dal momento che ne ho letto una di recente. Nella pagina man di bash puoi trovare un'enorme sezione intitolata HISTORY EXPANSION sull'argomento.

Puoi fare un intero host più che semplicemente eseguire l'ultimo comando o il numero di comando X. Puoi fare cose come !cateseguire l'ultimo comando che è iniziato con cat. Oppure !?bash?:s/bash/csh/esegue l'ultimo comando contenente bashma lo sostituisce con csh.


3
Sebbene non sia direttamente una risposta alla domanda di OP, ciò richiede molti più voti. Così utile! Grazie Havok.
Malvim,

Dovrei davvero guardare nella pagina man prima di iniziare a cercare su Google.
erikbwork,

1
!!:s/bash/csh/esegue effettivamente l' ultimo comando , quindi sostituisce bash con csh, se presente. Non l'ultimo comando che includeva bash. Sarebbe !?bash?:s/bash/csh/o forse!?bash?:s/%/csh/
cde

Avendo usato ampiamente Bash per diversi anni, sono rimasto scioccato nel constatare che non avevo mai saputo prima di questa parola chiave, e anche se ho passato ore a sfogliare le manpagine, questa funzione è incredibilmente oscura. Grazie per aver sottolineato la sezione pertinente: questo è l'unico posto nei documenti reali in cui lo spiegano sufficientemente.
Steve Benner,

39

Si può fare molto di più con !:

  • eseguire un comando che viene digitato prima di 3 comandi: !-3
  • eseguire un comando che inizia con !ls

e molto di più. Vedi 15 esempi di espansione della cronologia di Bash di Linux che dovresti conoscere


Ha valutato questo. Nessuna delle altre risposte ha avuto uno di questi trucchi intelligenti.
Gergely Lukacsy,

È stato votato perché www.thegeekstuff.com è semplicemente una risorsa fantastica, e questo è stato uno dei pochi articoli su Linux che non avevo mai visto prima. Molto utile.
Steve Benner,

4

Un mio amico mi ha inviato questa email:

Fa parte della libreria di storia GNU. In bash viene utilizzato per rieseguire i comandi nella cronologia. Se vuoi essere hardcore, grep per history_expansion_char in bash-4.1 / lib / readline / histexpand.c per i dettagli di implementazione.


3

Ovviamente puoi fare !!per riutilizzare l'ultimo comando nella shell bash. E poi c'è !$da riutilizzare l'ultima parte del tuo ultimo comando.

ad es. visualizzare alcuni file

less path/to/your/file.txt

Se ora desideri modificare lo stesso file, puoi utilizzare !$per ottenere solo il percorso del file dall'ultimo comando

vim !$

1
Ah, speravo di trovare questo. Come si comporta con due argomenti?
Jonathan,

Riutilizzerà solo l'ultimo argomento dei due. $touch f1 f2e poi $vim !$valuterà$vim f2
Teshan Shanuka J
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.