Jak mogę usunąć cały tekst między nawiasami klamrowymi w wielowierszowym pliku tekstowym?

10

Przykład:

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

Powinno stać się:

This is 
that wants
 anyway.

Znalazłem podobne wątki na forum, ale wydaje się, że nie działają one z nawiasami klamrowymi zawierającymi wiele wierszy.

Jeśli to możliwe, wolałbym metodę jednowierszową, na przykład rozwiązania oparte na grep, sed, awk ... itd.

EDYCJA: Rozwiązania wydają się być OK, ale zauważyłem, że moje oryginalne pliki zawierają zagnieżdżone nawiasy klamrowe. Otwieram więc nowe pytanie. Dziękujemy wszystkim: Jak mogę usunąć cały tekst między zagnieżdżonymi nawiasami klamrowymi w wielowierszowym pliku tekstowym?

Sopalajo de Arrierez
źródło
1
Spróbuj tegosed '/{/{:1;N;s/{.*}//;T1}' multiline.file
Costas

Odpowiedzi:

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

Wyjaśnienie:

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

    Spowoduje to odczytanie całego pliku do obszaru wzorów.

    :againto etykieta. Nczyta w następnym wierszu. $!b againwraca do againetykiety pod warunkiem, że nie jest to ostatni wiersz.

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

    To usuwa wszystkie wyrażenia w nawiasach klamrowych.

W systemie Mac OSX spróbuj:

sed -e ':again' -e N -e '$!b again' -e 's/{[^}]*}//g' file

Zagnieżdżone szelki

Weźmy to jako plik testowy z dużą ilością zagnieżdżonych nawiasów klamrowych:

a{b{c}d}e
1{2
}3{
}
5

Oto modyfikacja do obsługi zagnieżdżonych nawiasów klamrowych:

$ sed ':again;$!N;$!b again; :b; s/{[^{}]*}//g; t b' file2
ae
13
5

Wyjaśnienie:

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

    Jest tak samo jak poprzednio: czyta się w całym pliku.

  • :b

    To definiuje etykietę b.

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

    Spowoduje to usunięcie tekstu w nawiasach klamrowych, o ile tekst nie będzie zawierał nawiasów wewnętrznych.

  • t b

    Jeśli powyższe polecenie zastąpienia spowodowało zmianę, wróć do etykiety b. W ten sposób polecenie zastępcze jest powtarzane, aż wszystkie grupy nawiasów zostaną usunięte.

John1024
źródło
Twoja odpowiedź wydaje się idealna. Dopóki nowe pytanie, które właśnie otworzyłem (przeczytaj oryginalne pytanie EDIT), nie jest dokładnie takie samo, myślę, że powinieneś również na nie odpowiedzieć. Czy byłoby zgodne z regulaminem forum?
Sopalajo de Arrierez
@ John1024, możesz przenieść swoją edycję tutaj, ponieważ OP opublikował nowe pytanie dotyczące tego samego.
Ramesh
1
OK. Skopiowałem go tam i zmodyfikowałem, aby używał przykładowego tekstu w nowym pytaniu.
John1024,
5

Perl:

perl -0777 -pe 's/{.*?}//sg' file

Jeśli chcesz edytować w miejscu

perl -0777 -i -pe 's/{.*?}//sg' file

Odczytuje plik jako pojedynczy ciąg i wykonuje globalne wyszukiwanie i zamianę.

Będzie to obsługiwać zagnieżdżone stężenia:

perl -ne 'do {$b++ if $_ eq "{"; print if $b==0; $b-- if $_ eq "}"} for split //'
Glenn Jackman
źródło
Dziękuję, to było bardzo pomocne! Pomogło mi to rozwiązać problem ze skryptem kompilacji, który zastępuje zawartość funkcji w ciągu kilku minut w porównaniu do zmagania się z sed z ah..em, więcej czasu to przyznam (godziny .. kaszel .. kaszel)
AndrewD
4

Sed:

sed '/{/{:1;N;s/{.*}//;T1}' multiline.file

rozpoczęło się od linii z {i otrzymaj następną linię ( N), aż {}można dokonać podstawienia ( ) ( Toznacza powrót do znaku wykonanego przez, :jeśli podstawienie nie zostanie wykonane)

Trochę zmodyfikuj, aby było prawdziwe, jeśli wiele zawinięć w jednym wierszu

sed ':1; s/{[^}]*}// ; /{/ { /}/!N ; b1 }' multiline.file

Usuń wszystkie symbole w nawiasach (z [^}]wyjątkiem każdego symbolu,right bracket aby sednie był zachłanny), a jeśli pozostanie w wierszu left bracked- wróć, aby zacząć od dodanego następnego wiersza, jeśli nie ma right bracket.

Costas
źródło