Puoi fare qualcosa di rozzo con un piccolo script Perl che è incaricato di eseguire sostituzioni riga per riga ( -l -pe
) in posizione sui file passati come argomenti ( -i
):
perl -i -l -pe '
if (/from/) { # is the source text present on this line?
printf STDERR ("%s: %s [y/N]? ", $ARGV, $_); # display a prompt
$r=<STDIN>; # read user response
if ($r =~ /^[Yy]/) { # if user entered Y:
s/from/to/g; # replace all occurences on this line
}' /path/to/files
I possibili miglioramenti potrebbero essere la colorazione di parti del prompt e il supporto di elementi come "Sostituisci tutte le occorrenze nel file corrente". Promuovere separatamente ogni ricorrenza su una linea sarebbe più difficile.
Seconda parte, corrispondente ai file. se non ci sono troppi file coinvolti e stai eseguendo zsh, puoi abbinare ricorsivamente tutti i file nella directory corrente e nelle sue sottodirectory:
perl -i -l -pe '…' **/*(.)
Se la shell è bash ≥4, è possibile eseguire perl … **/*
, ma ciò produrrà messaggi di errore spuri perché sed tenterà (e non riuscirà) di funzionare su directory. Se si desidera eseguire la sostituzione solo in un set di file come i file C, è possibile limitare le corrispondenze (che funziona in bash ≥4 o zsh):
perl -i -l -pe '…' **/*.[hc]
Se hai bisogno di un controllo più preciso su quali file stai sostituendo, o la tua shell non ha il costrutto di corrispondenza della directory ricorsiva **
, o se hai troppi file e ottieni un errore di "riga di comando troppo lunga", usa find
. Ad esempio, per eseguire una sostituzione in tutti i file denominati *.h
o *.c
nella directory corrente e nelle sue sottodirectory (sui sistemi più vecchi, potrebbe essere necessario utilizzare \;
anziché +
alla fine della riga (il +
modulo è più veloce ma non disponibile ovunque).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
Detto questo, mi limiterei a un editor interattivo se hai bisogno di interazione. Gert ha mostrato un modo per farlo in Vim , anche se richiede l'apertura di tutti i file che si desidera cercare, il che potrebbe essere un problema se ce ne sono molti.
In Emacs, ecco come puoi farlo:
- Raccogliere i nomi dei file con
M-x find-name-dired
(specificare una directory di livello superiore) o M-x find-dired
(specificare una find
riga di comando arbitraria ).
- Nella risultante Dired tampone, premere
t
per contrassegnare tutti i file, quindi Q
( dired-do-query-replace-regexp
) per effettuare una sostituzione con spingendo sui file marcati.
s/from/to/g
un glitch di formattazione dopo di esso, piuttosto ches/from/to/gc
con enfasi suc
come avresti tentato di scrivere (non puoi farlo con Markdown, puoi farlo con<code>
e<strong>
tag HTML).