Beberapa pencarian dan ganti tindakan dalam satu file teks besar

11

Saya memiliki file teks besar (sekitar 2GB). Saya ingin melakukan lima pencarian dan mengganti tindakan pada file yang sama, dan ingin melakukan ini dalam satu perintah. Biasanya saya menggunakan vim, buka file, lakukan satu tindakan ganti, kemudian berikutnya, dll. Ada satu tangkapan, karena saya perhatikan bahwa setelah tiga atau empat pencarian vim crash karena masalah memori.

Berikut adalah dua contoh perintah yang saya gunakan di Vim:

:%s/www\.abcdef/www.test.abcdef/g 
:%s/www\.klmnop/www.test.klmnop/g

Apa cara terbaik untuk menangani ini?

SPRBRN
sumber

Jawaban:

8

Saya akan menggunakan sed seperti ini:

sed -i "s/www\.abcdef/www.test.abcdef/g;s/www\.kmlnop/www.test.klmnop/g;" yourfile.txt

-iOpsi singkatan dari pengganti "di tempat". Anda dapat memberitahu sed untuk membuat cadangan file Anda yang memberikan ekstensi untuk opsi ini ( -i.bakakan membuat cadangan file Anda sebagai file. File Anda ).

ssssteffff
sumber
Itu cepat! Bukan hanya jawaban Anda ;-) tetapi skrip dengan 5 pencarian dan penggantian ini sekitar 10x lebih cepat karena hanya membuka file di vim. Satu hal yang membingungkan saya. Pada awalnya saya pikir file .bak akan menjadi file yang diedit, tapi itu asli tentu saja.
SPRBRN
Sepuluh pencarian dan ganti tindakan (dengan ribuan klik) dalam file 2GB sekaligus, tanpa masalah memori. Kurang dari dua menit pada desktop rata-rata - super!
SPRBRN
Satu pertanyaan ... Anda lolos dari titik-titik dalam string ganti. Apakah ini perlu?
SPRBRN
1
Sama-sama @rxt :) Sebenarnya, Anda benar, Anda dapat menggunakan titik-titik yang tidak diloloskan dalam string pengganti sed. Saya mencoba, dan itu berhasil. Ada utas yang bagus di Unix & Linux Stackexchange , dan jawaban yang diterima tidak menyebutkan titik sebagai karakter untuk melarikan diri.
ssssteffff
2
@ rxt Anda mengatakan ganti string, maaf, tidak, Anda tidak perlu melarikan diri dari sana.
terdon
6

Jika Anda memiliki lebih banyak pola pencarian, Anda dapat menyimpannya dalam file dan membaca substitusi dari sana. Sebagai contoh, katakan ini adalah isi dari replacements.txt:

www\.abcdef www.test.abcdef 
www\.klmnop www.test.klmnop

Anda kemudian dapat membaca daftar penggantian N dan menggantinya dengan ini:

while read from to; do
  sed -i "s/$from/$to/" infile.txt ; 
done < replacements.txt 

CATATAN:

  • Ini mengasumsikan string pencarian Anda tidak mengandung spasi dan karakter aneh apa pun harus diloloskan replacements.txt.
  • Ini akan menjalankan satu sedper penggantian yang mungkin memakan waktu cukup lama jika Anda memiliki banyak operasi penggantian.
  • Itu dapat menangani sejumlah penggantian sewenang-wenang (ribuan atau jutaan atau apa pun) selama Anda tidak keberatan bahwa itu akan memakan waktu lebih lama.

Pilihan lain adalah menulis di atas sebagai sedskrip:

s/www\.abcdef/www\.test\.abcdef/g;
s/www\.kmlnop/www\.test\.klmnop/g;
s/aaaa/bbbb/g;
s/cccc/dddd/g;
s/eeee/ffff/g;

Anda kemudian dapat menjalankan skrip pada file Anda dan itu akan membuat semua penggantian dalam sekali jalan:

sed -f replace.sed infile.txt 
terdon
sumber
+1 untuk ,, opsi lain ''. Bisa jadi berguna untuk memiliki penggantian disimpan dalam file! (Kuharap aku akan mengingatnya ...)
mpy
+1 untuk "opsi lain" juga karena menggunakan fungsionalitas asli daripada skrip khusus, sehingga lebih portabel / dapat dibagikan
David Cook
@ Davidvid, terima kasih, tetapi tidak lebih asli atau portabel dari yang lain. Pendekatan pertama adalah menggunakan loop POSIX shell, itu persis portabel seperti yang kedua. Itu hanya akan jauh lebih lambat karena menggunakan shell loop.
terdon
Anda benar, yang saya maksudkan adalah bahwa format file skrip sed lebih mudah dibawa-bawa, karena ia menggunakan fungsionalitas bawaan daripada skrip, yang harus dibagi bersama dengan file replacements.txt. Namun demikian, keduanya adalah opsi hebat!
David Cook