2010-01-27 21 views
39

Se ho appena inserito il seguente comando in Bash:Caret ricerca e sostituzione nella shell Bash

echo foo 

posso cambiare foo al bar digitando:

^foo^bar 

che si traduce nella seguente comando in esecuzione:

echo bar 

Ora, se io entro:

012.
echo foo foo 

C'è un modo per cambiare entrambe le istanze di foo in bar semplicemente utilizzando l'operatore di caret (^)?

Inoltre, ci sono pagine man per operatori di shell come ^? man ^ restituisce "Nessuna immissione manuale per ^".

+2

Grazie per le risposte, è stato sperando in un modo per utilizzare la^sintassi per i duplicati dal è qualcosa che posso ricordare più facilmente ma sembra che dovrò memorizzare la versione del rumore di linea. – mattjames

+1

Potrebbe essere più facile per te ricordare la versione "rumore di linea" se pensi anche a '^ stringa1^stringa2' come già equivalente a' !!: s/stringa1/stringa2/'. – isomorphismes

+0

@mattjames se vuoi qualcosa di più facile da ricordare, puoi controllare la mia risposta, che è meno "rumore di linea" -y – MLP

risposta

48

tale caratteristica si chiama rapida sostituzione ; la sua documentazione è disponibile nella sezione Event Designators del Manuale di Bash. Non puoi fare ciò che vuoi con una sostituzione rapida; si dovrà ricorrere a qualcosa di un po 'più dettagliato:

!!:gs/foo/bar/ 
+0

@scanny: Questo non sembra essere documentato da nessuna parte, e non funziona per me in bash 4.2.10 (1). Quale versione della shell stai usando ('bash --version')? –

+0

Oops, mio ​​errore, 'zsh' sul cervello! : S ha eliminato il commento. – scanny

+0

La barra finale non era necessaria per me su OSX: '!!: gs/foo/bar' –

27

Né sicuro come farlo con la sostituzione del punto di inserimento, ma ecco come si fa con la storia:

!!:gs/foo/bar/ 

Permettetemi di rompere che verso il basso:

!! - ripete l'ultimo comando. È anche possibile utilizzare! -2 per eseguire due comandi fa,! Echo per eseguire l'ultimo comando che inizia con echo

: gs dice di eseguire una ricerca/sostituzione globale (tutte le istanze). Se si voleva fare basta sostituire la prima istanza, si usa ': s'

Infine,/foo/bar/dice per sostituire foo con bar

5

Caret sostituzione e altre scorciatoie simili si trovano nel eventi designatori sottosezione del ESPANSIONE DELLA STORIA sezione della pagina bash(1) dell'uomo.

1
^word^ ........... erase word 
^word^^ ........... delete everything until the end of the line 
+3

Entrambi fanno la stessa cosa per me: rimuove solo la parola dal comando. –

+0

Lo stesso qui. '% Echo "parola parola parola parola parola" parola parola parola parola parola %^parola ^^ echo "parola parola parola parola" parola parola parola parola ' – isomorphismes

21

Prova:

^foo^bar^:& 

Come sapete ^foo^bar^ esegue solo una sostituzione, e il modificatore :& ripete.

+9

Questo eseguirà due sostituzioni ma non una sostituzione globale. – isomorphismes

+2

Ho scoperto che è possibile passare in più ": &" modificatori alla sostituzione del caret. Quindi ": &" significa di nuovo, e ": &: &" significa ancora due volte e così via. (Ripetendo: e per ogni ripetizione diventerà noioso, e sono contento di sapere !! !!: gs //. – rickumali

0

Se stai cercando qualcosa di meno difficile da memorizzare che abbia lo stesso effetto del precedente !!:gs/foo/bar/, potresti sempre creare una funzione nel tuo script di avvio .bash_profile. Ho scelto replace().

replace() { 
    eval $(echo $(fc -ln -1) | eval "sed 's/${1}/${2}/g'") #compact form 
} 

o, meno convolutedly

replace() { 
    string=$(fc -ln -1) #gets last command string 
    repcmmd="sed 's/${1}/${2}/g'" #build replacement sed command from fn input 
    eval $(echo $string | eval $repcmmd) #evaluates the replacement command 
} 

Poi il Sostituisci tutto può essere fatta con

echo foo foo 
replace foo bar 
Problemi correlati