Bagaimana cara mengganti kode multi-baris dengan sed?

9

Saya memiliki file besar yang memiliki karakter khusus di dalamnya. Ada kode multi-line di sana, yang ingin saya ganti sed.

Ini:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

Perlu diubah menjadi ini:

text = ""

Saya mencoba kode berikut, tetapi tidak berhasil:

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

Itu tidak menggantikan apa pun dan tidak menampilkan pesan kesalahan apa pun

Saya telah bermain dengannya, tetapi semua yang saya coba tidak berhasil.

blade19899
sumber
Apakah perlu sedatau Anda terbuka untuk alat lain? Bisa ada "di dalam text=blok? Bisakah ada kasus lain text = dalam file Anda? Akankah selalu ada 4 baris teks atau dapatkah ada lebih / kurang?
terdon
Lebih disukai sed, atau apa pun yang tidak memerlukan instalasi di server CentOS. Alat luar kotak
blade19899
@terdon Tidak ada yang lain text = di folder, yang keluar harus text = "". File-file ini memiliki 891 baris kode. JADI, perlu menghormati teks lain.
blade19899
Anda ingin menimpa file atau hanya memodifikasi output?
joH1
@Moonstroke NO OVERWRITE. Itu hanya perlu mengganti teks - seperti yang terlihat dalam pertanyaan saya - untuk text = "". Seperti yang terlihat dalam pertanyaan saya.
blade19899

Jawaban:

15

Perl untuk penyelamatan:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ akan mengedit file "di tempat", meninggalkan salinan cadangan
  • -0777 membaca seluruh file sekaligus, bukan baris demi baris

Substitusi s///bekerja sama seperti dalam sed (yaitu cocok text = "dengan diikuti oleh apa pun kecuali tanda kutip berkali-kali hingga tanda kutip ganda), tetapi dalam kasus ini, ia bekerja pada seluruh file.

choroba
sumber
5

Anda harus memeriksa ruang pola dan terus menarik Ngaris ext jika tidak cocok misalnya

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

dengan gnu sedAnda dapat menuliskannya sebagai

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

Itu tidak terlalu efisien, lebih baik pilih rentang /text = "/,/"/, modifikasi baris pertama dan hapus sisanya:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

lagi, dengan gnu sedAnda dapat menuliskannya sebagai satu-baris:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile
don_crissti
sumber
3

Secara pribadi, saya akan melakukan ini di Perl. Jika kita dapat berasumsi bahwa tidak ada "sebelum penutupan ", Anda dapat melakukan:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

The -0slurps seluruh file, membaca ke dalam memori. The -pberarti "mencetak setiap baris (di sini, 'garis' akan seluruh file) setelah menerapkan script yang diberikan oleh -e". Script itu sendiri adalah operator substitusi sederhana. Ini akan menangkap string textdiikuti oleh 0 atau lebih karakter spasi, =dan 0 atau lebih spasi putih lagi ( text\s*=\s*) dan simpan sebagai $1. Kemudian, itu akan menggantikan pola yang ditangkap serta string yang dikutip terpendek yang ditemukannya dengan pola ( $1) dan "". The sflag membuat .baris baru pertandingan.

terdon
sumber
koreksi, -00dibaca dalam paragraf, bukan seluruh file ( ref ). Jika teks dalam tanda kutip berisi baris kosong, maka regex tidak akan cocok.
glenn jackman
@glennjackman argh! Saya selalu campur aduk. . Itulah sebabnya saya benar-benar memeriksa ulang dengan menambahkan paragraf tambahan dan menjalankan perl -00ne 'print;exit'. Dan saya masih memasukkan jawaban yang salah! Terima kasih, perbaiki sekarang.
terdon