Comment supprimer tout le texte entre accolades dans un fichier texte multiligne?

10

Exemple:

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

Devrait devenir:

This is 
that wants
 anyway.

J'ai trouvé des fils similaires sur le forum, mais ils ne semblent pas fonctionner avec des accolades multi-lignes.

Si possible, je préférerais une méthode en ligne, comme des solutions basées sur grep, sed, awk ... etc.

EDIT: Les solutions semblent être correctes, mais j'ai remarqué que mes fichiers d'origine incluent l'imbrication des accolades. J'ouvre donc une nouvelle question. Merci à tous: Comment supprimer tout le texte entre des accolades imbriquées dans un fichier texte multiligne?

Sopalajo de Arrierez
la source
1
Essayez cecised '/{/{:1;N;s/{.*}//;T1}' multiline.file
Costas

Réponses:

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

Explication:

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

    Ceci lit le fichier entier dans l'espace modèle.

    :againest une étiquette. Nlit dans la ligne suivante. $!b againramène à l' againétiquette à condition que ce ne soit pas la dernière ligne.

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

    Cela supprime toutes les expressions entre accolades.

Sur Mac OSX, essayez:

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

Accolades imbriquées

Prenons cela comme un fichier de test avec beaucoup d'accolades imbriquées:

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

Voici une modification pour gérer les accolades imbriquées:

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

Explication:

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

    C'est la même chose qu'avant: il lit dans tout le fichier.

  • :b

    Cela définit une étiquette b.

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

    Cela supprime le texte entre accolades tant que le texte ne contient pas d'accolades internes.

  • t b

    Si la commande de substitution ci-dessus a entraîné une modification, revenez à l'étiquette b. De cette façon, la commande de substitution est répétée jusqu'à ce que tous les groupes d'accolades soient supprimés.

John1024
la source
Votre réponse semble parfaite. Tant que la nouvelle question que je viens d'ouvrir (lire la question d'origine EDIT) n'est pas exactement la même, je pense que vous devriez également y répondre. Serait-ce OK avec les règles du forum?
Sopalajo de Arrierez
@ John1024, vous pouvez déplacer votre modification ici car le PO a posté une nouvelle question à ce sujet.
Ramesh
1
D'ACCORD. Je l'ai copié là-bas et l'ai modifié pour utiliser l'exemple de texte dans la nouvelle question.
John1024
5

Perl:

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

Si vous souhaitez éditer sur place

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

Cela lit le fichier comme une chaîne unique et effectue une recherche et un remplacement global.

Cela gérera les contreventements imbriqués:

perl -ne 'do {$b++ if $_ eq "{"; print if $b==0; $b-- if $_ eq "}"} for split //'
glenn jackman
la source
Merci, cela m'a beaucoup aidé! Cela m'a aidé à résoudre un problème avec un script de construction pour remplacer le contenu d'une fonction en quelques minutes vs lutter avec sed avec ah..em, plus de temps que je l'admettrai (hours..cough..cough)
AndrewD
4

Sed:

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

commencé depuis la ligne avec {et obtenir la ligne suivante ( N) jusqu'à ce que la substitution ( {}) puisse être effectuée ( Tsignifie retourner à la marque faite par :si la substitution n'est pas effectuée)

Un peu modifier pour être vrai si plusieurs boucles sont entre crochets sur une seule ligne

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

Retirez tous les symboles dans les crochets ( [^}]égale à tous les exepté symboleright bracket faire sedpas gourmand), et si la ligne reste left bracked- retour au début avec la ligne suivante ajouté s'il n'y a pas right bracket.

Costas
la source