Prova la ricerca sed ricorsiva e sostituiscila prima di eseguire


13

Esiste un modo per eseguire una ricerca ricorsiva di prova e sostituirla con sed, prima di eseguirla effettivamente? Voglio solo stampare i risultati prima di fare effettivamente la ricerca e sostituirli. Qualcosa come l'eco dei risultati di,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'

Fai una copia dei dati, esegui il tuo comando, controlla il risultato.
Kusalananda

Risposte:


10

È possibile eseguire sedsenza -ie scorrere l'output conless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Quindi eseguire sedcon -i.bakper creare backup che è possibile diff in seguito

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Modifica: come suggerito nel commento, utilizzare grep --null | xargs -0. Questo fa sì che i nomi dei file vengano chiusi dal byte null, il che lo rende sicuro per i nomi di file con caratteri insoliti come newline. Sì, \nè un carattere valido in un nome file unix. Gli unici personaggi proibiti sono la barra /e il personaggio nullo\0


Interessante, ho provato a trovare il significato di -i ma non era elencato sotto man sed. La tua soluzione ha funzionato. Quale sarebbe il modo migliore secondo te per elencare solo le linee, non l'intero file? Invece di convogliare in meno ho convogliato | grep term2, che in qualche modo ha funzionato, ma ho anche ottenuto un output con strani personaggi.
user251482,

@ user251482 - "Elenca solo le righe", come in "visualizzare un diff tra il vecchio e il nuovo file"?
Grebneke,

1
@StephaneChazelas Sì, o meglio grep -rl --nullperché OP non ha specificato il sistema operativo e -Zsignifica qualcosa di diverso su BSD / OSX (decomprimere). --nullè lo stesso su GNU e BSD
grebneke il

1
@grebneke. Buon punto, ma nota che l'OP sta usando la sintassi sed di GNU, quindi possiamo presumere che non sia su BSD. Nota che grepè (un fork di) il grep GNU su FreeBSD e NetBSD. Su NetBSD, -Zsignifica ancora --null(secondo la pagina man), ma sono d'accordo - niente è più portatile. Si noti inoltre che né --null né -Z funzionano su OpenBSD
Stéphane Chazelas il

1
@grebneke, è sed -i '' -e s/.../in BSD sed(nessuna opzione opzionale lì)
Stéphane Chazelas,

5

Utilizzare sedcon findinvece digrep

Prima di tutto, vorrei impiegare findpiuttosto che grep, e questo per tre buoni motivi:

  1. findconsente una selezione più precisa dei file. Ad esempio, grep -r string *.txtprodurrà i file solo nella directory corrente; non quelli nelle sottodirectory.
  2. findviene fornito con la potente -execopzione che elimina la necessità dell'intero --null … |xargs 0costrutto.
  3. Le opzioni -readablee -writabledi findimpediranno di perdere tempo con i file a cui non è possibile accedere.

Test di acquisizione

Detto questo, grepsi presta per un primo test per vedere cosa verrebbe catturato:

$ find . -exec grep term1 {} \;

o più specificamente:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Funzionamento a secco

Ora procedi con una sedcorsa a secco. L' sedopzione -nè sinonimo di --quiete palla fine seddell'espressione stamperà lo spazio del motivo corrente.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

o più specificamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Esecuzione

Se tutto sembra a posto, emetti il ​​comando definitivo sostituendo l' sedopzione -ncon -i"sul posto" e rimuovendo il palla fine.

$ find . -exec sed -i 's/term1/term2/g' {} \;

o più specificamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Più findesempi

Altri findesempi possono essere trovati qui .

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.