2009-02-09 14 views
33

qual è il modo migliore per farlo? non sono un guerriero da linea di comando, ma pensavo che ci fosse un modo per usare grep e cat.Il modo migliore per trovare/sostituire in diversi file?

Voglio solo sostituire una stringa che si verifica in una cartella e sottocartelle. qual'è il miglior modo per farlo? sto usando Ubuntu se questo è importante.

-d

+0

Basta lasciare questo link qui: http://stackoverflow.com/questions/102083/whats-the-best-tool-to-find-and-replace-regular-expressions-over-multiple-files –

risposta

36
find . -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g' 

La prima parte di questo è un comando find per trovare i file che si desidera modificare. Potrebbe essere necessario modificarlo in modo appropriato. Il comando "xargs" prende ogni file trovato e applica il comando "sed" ad esso. Il comando "sed" prende ogni istanza di "from" e lo sostituisce con "to". Questa è un'espressione regolare standard, quindi modificala come ti serve.

Se si sta utilizzando svn, attenzione. Le tue directory .svn saranno anche ricercate e sostituite. Bisogna escludere quelli, per esempio, in questo modo:

find . ! -regex ".*[/]\.svn[/]?.*" -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'

o

find . -name .svn -prune -o -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'

+0

non sembra che questo comando ricorra nelle sottodirectory. c'è qualcosa che sto sbagliando? – blackrobot

+0

Cosa ti fa pensare che non ricorre nelle directory? –

+0

i file di testo nelle sottodirectory non stanno apportando le modifiche. ciò che voglio fare è questo: cambiare le occorrenze di some.ip.address su somewebsite.com in tutte le sottodirectory. – blackrobot

37

Come disse Paolo, si desidera trovare prima i file che si desidera modificare e poi modificarli. Un'alternativa all'utilizzo di ritrovamento è quello di utilizzare GNU grep (il default su Ubuntu), ad esempio:

grep -r -l from . | xargs -0 -n 1 sed -i -e 's/from/to/g' 

È inoltre possibile utilizzare ACK-grep (sudo apt-get install ACK-grep o visitare http://petdance.com/ack/), nonché, se sai che vuoi solo un certo tipo di file e vuoi ignorare le cose nelle directory di controllo della versione. ad esempio, se desideri solo i file di testo,

ack -l --print0 --text from | xargs -0 -n 1 sed -i -e 's/from/to/g' 
# `from` here is an arbitrary commonly occurring keyword 

alternativa all'utilizzo sed è di usare Perl in grado di elaborare più file per comando, per esempio,

grep -r -l from . | xargs perl -pi.bak -e 's/from/to/g' 

Qui, perl è raccontata da modificare in posto, creando prima un file .bak.

È possibile combinare uno qualsiasi dei lati sinistro del tubo con i lati a destra, a seconda delle proprie preferenze.

+0

È possibile evitare le directory di controllo della versione in "trova" utilizzando il comando "-prune". Per esempio "trova. -name RCS -prune -o -type f -print0" –

+0

Vero, anche se richiede meno intelligenza per avere uno strumento come Ack gestirlo per te. –

+0

ack accetta anche un'opzione '--print0' per usare null come delimitatore tra i nomi dei file, quindi il comando ack sarà simile a questo:' ack -l --print0 --text from | xargs -0 -n 1 sed -i -e 's/from/to/g'' –

3

Un'alternativa a sed sta usando rpl (ad esempio disponibile presso http://rpl.sourceforge.net/ o la vostra distribuzione GNU/Linux), come rpl --recursive --verbose --whole-words 'F' 'A' grades/

14

mi butto in un altro esempio per la gente che utilizzano Ag, The Silver Searcher fare trovare/sostituire le operazioni su più file .

Esempio completo:

ag -l "search string" | xargs sed -i '' -e 's/from/to/g' 

Se rompiamo questo in giù, quello che otteniamo è:

# returns a list of files containing matching string 
ag -l "search string" 

Avanti, abbiamo:

# consume the list of piped files and prepare to run foregoing command 
# for each file delimited by newline 
xargs 

Infine, il comando sostituzione di stringa :

# -i '' means edit files in place and the '' means do not create a backup 
# -e 's/from/to/g' specifies the command to run, in this case, 
# global, search and replace 

sed -i '' -e 's/from/to/g' 
Problemi correlati