Bagaimana saya bisa menghapus semua teks di antara kurung keriting bersarang dalam file teks multiline?

9

Pertanyaan ini berasal dari Bagaimana cara saya menghapus semua teks di antara kurung keriting dalam file teks multiline? (Sama saja, tetapi tanpa persyaratan untuk bersarang).

Contoh:

This is {
{the multiline
text} file }
that wants
{ to {be
changed}
} anyway.

Harus menjadi:

This is 
that wants
 anyway.

Apakah mungkin untuk melakukan ini dengan semacam perintah bash satu baris (awk, sed, perl, grep, cut, tr ... dll)?

Sopalajo de Arrierez
sumber

Jawaban:

13
$ sed ':again;$!N;$!b again; :b; s/{[^{}]*}//g; t b' file3
This is 
that wants
 anyway.

Penjelasan:

  • :again;$!N;$!b again

    Ini berbunyi di seluruh file.

    :againadalah label. Nmembaca di baris berikutnya dan $!Nmembaca di baris berikutnya dengan syarat kita belum berada di baris terakhir. $!b againcabang kembali ke againlabel dengan syarat bahwa ini bukan baris terakhir.

  • :b

    Ini mendefinisikan label b.

  • s/{[^{}]*}//g

    Ini menghapus teks dalam kawat gigi selama teks tidak mengandung kawat gigi dalam.

  • t b

    Jika perintah pengganti di atas menghasilkan perubahan, lompat kembali ke label b. Dengan cara ini, perintah pengganti diulangi sampai semua brace-groups dihilangkan.

John1024
sumber
3

Pendekatan Perl:

$ perl -F"" -a00ne 'for (@F){$i++ if /{/; $i||print; $i-- if /}/}' file
This is 
that wants
 anyway

Penjelasan

  • -a: mengaktifkan pemisahan otomatis pada pembatas file yang diberikan oleh -Fke dalam @Farray.
  • -F"": mengatur pemisah bidang input menjadi kosong yang akan menghasilkan setiap elemen @Fmenjadi salah satu karakter input.
  • -00: nyalakan "mode paragraf", di mana "baris" didefinisikan sebagai dua karakter baris baru berturut-turut. Ini berarti bahwa seluruh file dalam kasus ini akan diperlakukan sebagai satu baris. Jika file Anda dapat memiliki banyak paragraf dan tanda kurung dapat menjangkau beberapa paragraf, gunakan -0777saja.
  • -ne: baca file input dan terapkan skrip yang diberikan oleh -euntuk setiap baris.

Script itu sendiri sebenarnya cukup sederhana. Penghitung bertambah satu oleh setiap kali {dilihat dan dikurangi oleh satu untuk setiap }. Ini berarti bahwa ketika penghitung adalah 0, kita tidak berada di dalam tanda kurung dan harus mencetak:

  • for (@F){}: lakukan ini untuk setiap elemen @F, setiap karakter di baris.
  • $i++ if /{/;: increment $iby one jika karakter ini adalah a{
  • $i||print;: cetak kecuali $idiatur (0 dianggap tidak disetel).
  • $i-- if /}/: decrement $iby one jika karakter ini adalah a}
terdon
sumber