¿Cómo puedo eliminar todo el texto entre llaves en un archivo de texto multilínea?

10

Ejemplo:

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

Debe convertirse:

This is 
that wants
 anyway.

Encontré algunos hilos similares en el foro, pero no parecen funcionar con llaves de varias líneas.

Si es posible, preferiría algún método de una línea, como soluciones basadas en grep, sed, awk ... etc.

EDITAR: Las soluciones parecen estar bien, pero he notado que mis archivos originales incluyen la anidación de llaves. Entonces estoy abriendo una nueva pregunta. Gracias a todos: ¿Cómo puedo eliminar todo el texto entre llaves en un archivo de texto de varias líneas?

Sopalajo de Arrierez
fuente
1
Prueba estosed '/{/{:1;N;s/{.*}//;T1}' multiline.file
Costas el

Respuestas:

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

Explicación:

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

    Esto lee todo el archivo en el espacio del patrón.

    :againEs una etiqueta. Nlee en la siguiente línea. $!b againvuelve a la againetiqueta con la condición de que esta no sea la última línea.

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

    Esto elimina todas las expresiones entre llaves.

En Mac OSX, intente:

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

Tirantes anidados

Tomemos esto como un archivo de prueba con muchas llaves anidadas:

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

Aquí hay una modificación para manejar llaves anidadas:

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

Explicación:

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

    Esto es lo mismo que antes: se lee en todo el archivo.

  • :b

    Esto define una etiqueta b.

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

    Esto elimina el texto entre llaves siempre que el texto no contenga llaves internas.

  • t b

    Si el comando sustituto anterior resultó en un cambio, vuelva a la etiqueta b. De esta manera, el comando sustituto se repite hasta que se eliminan todos los grupos de llaves.

John1024
fuente
Tu respuesta parece ser perfecta. Mientras la nueva pregunta que acabo de abrir (lea la pregunta original EDIT) no sea exactamente la misma, creo que debería responderla también. ¿Estaría bien con las reglas del foro?
Sopalajo de Arrierez
@ John1024, puede mover su edición aquí ya que el OP publicó una nueva pregunta con respecto a la misma.
Ramesh
1
OKAY. Lo copié allí y lo modifiqué para usar el texto de muestra en la nueva pregunta.
John1024
5

Perl:

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

Si desea editar en el lugar

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

Eso lee el archivo como una sola cadena y realiza una búsqueda y reemplazo global.

Esto manejará arriostrados anidados:

perl -ne 'do {$b++ if $_ eq "{"; print if $b==0; $b-- if $_ eq "}"} for split //'
Glenn Jackman
fuente
¡Gracias, esto fue de gran ayuda! Esto me ayudó a resolver un problema con un script de compilación para reemplazar el contenido de una función en cuestión de minutos frente a luchar con sed con ah..em, más tiempo de lo que admitiré (horas
tos ...
4

Sed:

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

comenzó desde la línea con {y obtiene la siguiente línea ( N) hasta que {}se pueda realizar la sustitución ( ) ( Tsignifica volver a la marca realizada :si no se realiza la sustitución)

Un poco de modificación para que sea cierto si muchas curvas se rompen en una línea

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

Elimine todos los símbolos entre paréntesis ( [^}]igual a cada símbolo exceptoright bracket para que sedno sea codicioso), y si permanece en la línea left bracked, regrese para comenzar con la siguiente línea agregada si no la hay right bracket.

Costas
fuente