¿Cómo reemplazar un código de varias líneas con sed?

9

Tengo un archivo grande que tiene caracteres especiales. Hay un código de varias líneas allí, con el que quiero reemplazar sed.

Esta:

  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"

Necesita convertirse en esto:

text = ""

Intenté el siguiente código, pero no tuve suerte:

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

No reemplaza nada y no muestra ningún mensaje de error

He estado jugando con él, pero todo lo que intento no funciona.

cuchilla19899
fuente
¿Necesita ser sedo estás abierto a otras herramientas? ¿Puede haber "dentro del text=bloque? ¿Puede haber otros casos text = en su archivo? ¿Habrá siempre 4 líneas de texto o puede haber más / menos?
terdon
Preferiblemente sed, o cualquier cosa que no requiera instalación en un servidor CentOS. Herramientas
listas para usar
@terdon No hay otros text = en la carpeta, el resultado debe ser text = "". Los archivos tienen 891 líneas de código. Por lo tanto, debe respetar el otro texto.
blade19899
¿Desea sobrescribir el archivo o simplemente modificar la salida?
joH1
@ Mooonstroke NO SOBRESCRIBIR. Solo necesita reemplazar el texto, como se ve en mi pregunta, a text = "". Como se ve en mi pregunta.
blade19899

Respuestas:

15

Perl al rescate:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ editará el archivo "en su lugar", dejando una copia de seguridad
  • -0777 lee todo el archivo a la vez, no línea por línea

La sustitución s///funciona de manera similar a como en sed (es decir, coincide text = "seguido de cualquier cosa menos comillas dobles muchas veces hasta una comilla doble), pero en este caso, funciona en todo el archivo.

choroba
fuente
5

Debe verificar el espacio del patrón y seguir tirando de la Nlínea de extensión si no coincide, por ejemplo

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

con gnu sedusted puede escribirlo como

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

Sin embargo, eso no es muy eficiente, mejor solo seleccione el rango /text = "/,/"/, modifique la primera línea y elimine el resto:

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)

de nuevo, con gnu sedusted puede escribirlo como una línea:

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

Personalmente, haría esto en Perl. Si podemos suponer que no hay "antes del cierre ", puede hacer:

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

El -0sorbe todo el archivo, leyéndolo en la memoria. El -pmedio "imprime cada línea (aquí, una" línea "será el archivo completo) después de aplicar la secuencia de comandos dada por -e". El script en sí es un operador de sustitución simple. Capturará la cadena textseguida de 0 o más espacios en blanco, an =y 0 o más espacios en blanco nuevamente ( text\s*=\s*) y la guardará como $1. Luego, reemplazará el patrón capturado, así como la cadena citada más corta que encuentre con el patrón ( $1) y "". La sbandera hace .coincidir las nuevas líneas.

terdon
fuente
corrección, -00lee en párrafos, no todo el archivo ( ref ). Si el texto entre comillas contiene una línea en blanco, la expresión regular no coincidirá.
Glenn Jackman
@glennjackman argh! Siempre los mezclo. . Es por eso que realmente verifiqué dos veces agregando un párrafo adicional y ejecutándolo perl -00ne 'print;exit'. ¡Y todavía pongo el incorrecto en mi respuesta! Gracias, arreglado ahora.
terdon