Ganti string multiline dalam file

17

Saya memiliki sejumlah file yang ingin saya perbarui dengan mengganti satu string multi-line dengan string multi-line lainnya. Sesuatu di sepanjang garis:

* Some text, 
* something else
* another thing

Dan saya ingin menggantinya dengan:

* This is completely
* different text

Hasilnya adalah bahwa setelah penggantian file yang berisi blok teks pertama, sekarang akan berisi string kedua (sisa file tidak berubah).

Bagian dari masalahnya adalah saya harus menemukan daftar file yang akan diperbarui dalam sistem file. Saya kira saya dapat menggunakan grep untuk itu (meskipun sekali lagi itu tidak mudah dilakukan dengan string multiline) lalu pipa itu sed sed mungkin?

Apakah ada cara mudah untuk melakukan ini? Sed adalah pilihan tetapi canggung karena saya harus menambahkan \ n dll. Apakah ada cara untuk mengatakan "ambil input dari file ini, cocokkan di file-file itu, lalu ganti dengan konten dari file lain ini"? Saya dapat menggunakan python jika perlu, tetapi saya menginginkan sesuatu yang cepat dan sederhana, jadi jika ada utilitas yang tersedia, saya lebih suka menggunakannya daripada menulis skrip saya sendiri (yang saya tahu caranya).

ventsyv
sumber
Anda mungkin harus menggunakan perl untuk ini. stackoverflow.com/questions/1030787/…
orion
3
Jadi, Anda ingin mencocokkan some text, something else another thingapakah itu mencakup beberapa baris atau tidak? Atau Anda hanya ingin mencocokkan some text,\nsomething else\nanotherthing?
mikeserv
2
Edit pertanyaan Anda dan jelaskan apa sebenarnya isi setiap file, dan apa output yang diinginkan.
jimmij
String ini mencakup beberapa baris. Saya agak mengabaikan spasi ketika mencocokkan / mengganti karena mungkin tidak semuanya sama, tetapi itu bukan masalah besar jika saya hanya melakukan pertandingan 1-1 (baris baru dan semua).
ventsyv

Jawaban:

12

Ganti "Some ... \ n ... Thing" dengan isi file "baru" dalam satu atau lebih file input

perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
  1. -i untuk mengubah input.txt secara langsung
  2. -p0 masukkan file file input dan cetak pada akhirnya
  3. s/regexp/.../s di regexp .adalah.|\n
  4. s/.../exp/e ganti dengan eval(exp)
  5. baru - file yang berisi teks pengganti (Ini benar-benar ... teks yang berbeda)
  6. jika berguna Anda dapat memperluas teks asli s/Some text\n...\n...thing\n/...
Joao
sumber
Bagaimana saya bisa melakukan hal yang sama dengan file bernama say "before" untuk mencari konten (multi-line) dari file itu? Saya mencoba tetapi tidak berhasil.
Kvothe
@ Kothoth, kita perlu lebih banyak detail ... Dengan anggapan bahwa "sebelum" tidak memiliki karakter khusus, Anda dapat mencobaperl -i -p0e ' $b= `cat before`; s/$b/Some thing\n/se' input.txt ...
JJoao
Dan dengan asumsi "sebelum" berisi semua karakter khusus (baris baru, garis miring, tanda kurung) kecuali 'dan `.
Kvothe
5
sed -e :n -e '$!N;/\n.*\n/!{$!bn
};  s/some text,\n* *something else\n* *another thing/this is completely\
different text/;P;D' <infile

Saya khawatir Anda akan mengalami kesulitan menghasilkan solusi yang cocok untuk Anda sampai Anda menyelesaikan deskripsi masalah yang konkret - tapi itulah yang paling cocok untuk QA, seperti yang saya lihat. Mungkin ini akan memberi Anda ide - itu akan selalu menjaga 3 baris dalam ruang pola pada suatu waktu - dengan 2 baris lookahead - sambil meluncur maju melalui file input hanya satu baris pada suatu waktu.

Itu harus dapat mencocokkan string Anda apakah itu mencakup beberapa baris atau tidak - hingga tiga, yaitu. Tetapi tidak ada ketentuan untuk mencerminkan ketentuan itu dalam penggantian - itu selalu mencakup dua baris seperti yang tertulis.

mikeserv
sumber
0

Tidak kuat (karena jangan chech string kedua tetapi mudah untuk menyelesaikan) dan bisa tidak posix compilant tetapi sangat sederhana:

sed '/^Some text/{:1;/another thing$/!{N;b 1}
     s/.*/this is completely\ndifferent text/g}' input.txt

Perintah pertama menambahkan baris dari Beberapa teks sampai bertemu hal lain, kemudian baris kedua mengubahnya ke teks lain.

CATATAN Batasannya adalah bahwa beberapa teks harus selalu diikuti oleh hal lain .

Costas
sumber
Masalahnya adalah bahwa string mungkin lebih dari 2 baris (hingga selusin atau lebih) dan mungkin berisi hal-hal lain yang mungkin perlu diloloskan, seperti tab, * dll.
ventsyv
@ventsyv Tidak ada masalah dengan jumlah garis atau pemisah - skrip memeriksa awal dan akhir saja. Ini cukup memadai JIKA string mulai secara eksternal dapat menandai teks untuk berubah . Jika tidak ada yang lebih baik, tunjukkan contoh input untuk menghasilkan pola yang benar.
Costas