
Tengo un archivo grande que tiene caracteres especiales. Hay un código de varias líneas allí que quiero reemplazar con sed
.
Este:
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 = ""
Probé 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.
Respuesta1
Perl al rescate:
perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
-i~
editará el archivo "in situ", 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 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.
Respuesta2
Tienes que verificar el espacio del patrón y seguir tirando de la N
línea externa 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 sed
puedes escribirlo como
sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile
Sin embargo, eso no es muy eficiente, mejor simplemente 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, gnu sed
puedes escribirlo en una sola línea:
sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile
Respuesta3
Personalmente, haría esto en Perl. Si podemos suponer que no hay "
antes del cierre "
, puedes hacer:
perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file
Sorbe -0
el archivo completo y lo lee en la memoria. Significa -p
"imprimir cada línea (aquí, una "línea" será el archivo completo) después de aplicar el script proporcionado por -e
". El script en sí es un operador de sustitución simple. Capturará la cadena text
seguida de 0 o más espacios en blanco, =
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 entre comillas más corta que encuentre, con el patrón ( $1
) y ""
. La s
bandera hace .
coincidir nuevas líneas.