Uji pencarian sed berulang dan ganti sebelum berjalan

13

Apakah ada cara untuk menjalankan pencarian rekursif dan mengganti menggunakan sed, sebelum benar-benar menjalankannya? Saya hanya ingin mencetak hasilnya sebelum benar-benar melakukan pencarian dan ganti. Sesuatu seperti menggemakan hasil,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
pengguna251482
sumber
Buat salinan data, jalankan perintah Anda, periksa hasilnya.
Kusalananda

Jawaban:

10

Anda dapat menjalankan sedtanpa -idan melangkah melalui output denganless

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

Kemudian jalankan seddengan -i.bakuntuk membuat cadangan yang dapat Anda bedakan sesudahnya

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

Sunting: Seperti yang disarankan dalam komentar, gunakan grep --null | xargs -0. Ini menyebabkan nama file diakhiri oleh byte-nol, yang membuatnya aman untuk nama file dengan karakter yang tidak biasa seperti baris baru. Ya, \nadalah karakter yang valid dalam nama file unix. Satu-satunya karakter terlarang adalah slash /dan karakter nul\0

grebneke
sumber
Menarik, saya mencoba menemukan arti -i tetapi tidak terdaftar di bawah man sed. Solusi Anda berhasil. Apa yang akan menjadi cara terbaik menurut Anda untuk hanya daftar baris, bukan seluruh file? Alih-alih perpipaan menjadi lebih sedikit saya disalurkan | grep term2, yang semacam bekerja tetapi saya mendapat beberapa output dengan karakter aneh juga.
user251482
@ user251482 - "Cukup daftarkan baris", seperti pada "melihat perbedaan antara file lama dan baru"?
grebneke
1
@StephaneChazelas Ya, atau bahkan lebih baik grep -rl --nullkarena OP tidak menentukan OS, dan -Zberarti sesuatu yang berbeda pada BSD / OSX (dekompresi). --nullsama pada GNU dan BSD
grebneke
1
@grebneke. Poin bagus, tetapi perhatikan bahwa OP menggunakan sintaks sed GNU, jadi kita bisa berasumsi dia tidak menggunakan BSD. Perhatikan bahwa grep(garpu) GNU grep pada FreeBSD dan NetBSD. Di NetBSD, -Zmasih berarti --null(menurut halaman manual), tapi saya setuju --null lebih portabel. Perhatikan juga bahwa --null maupun -Z tidak bekerja pada OpenBSD
Stéphane Chazelas
1
@ grebneke, ada sed -i '' -e s/.../di BSD sed(tidak ada opsi opsional di sana)
Stéphane Chazelas
5

Gunakan seddengan findalih - alihgrep

Pertama-tama, saya akan mempekerjakan finddaripada grep, dan ini karena tiga alasan bagus:

  1. findmemungkinkan untuk pemilihan file yang lebih tepat. Misalnya, grep -r string *.txtakan menghasilkan file hanya di direktori saat ini; bukan yang ada di subdirektori.
  2. findhadir dengan -execopsi kuat yang menghilangkan kebutuhan untuk keseluruhan --null … |xargs 0konstruksi.
  3. The -readabledan -writableopsi findakan mencegah membuang-buang waktu pada file yang tidak dapat diakses.

Tes pengambilan

Yang mengatakan, grepapakah cocok untuk tes pertama untuk melihat apa yang akan ditangkap:

$ find . -exec grep term1 {} \;

atau lebih khusus:

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

Lari kering

Sekarang, lanjutkan dengan sedlari kering. The sedpilihan -nadalah sinonim untuk --quietdan pdi akhir dari sedekspresi akan mencetak ruang pola arus.

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

atau lebih khusus:

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

Eksekusi

Jika semuanya terlihat baik-baik saja, keluarkan perintah definitif dengan mengganti sedopsi -ndengan -iuntuk "di tempat" dan dengan menghapus pdi akhir.

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

atau lebih khusus:

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

Lebih banyak findcontoh

Lebih banyak findcontoh dapat ditemukan di sini .

Serge Stroobandt
sumber