Sustituya el patrón dentro de un archivo con el contenido de otro archivo

20

Tengo un archivo de texto ( devel.xml).

Le agregué la palabra REPLACETHIS para reemplazar esta cadena con el contenido dentro de un archivo diferente ( temp.txt).

Lo más cercano que tengo es esto:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

Esto inserta el contenido después de la cadena y luego elimina la cadena.

¿Es esta la mejor manera de hacerlo?

RafaelGP
fuente
¿Tiene que ser sed? Dependiendo de cuánto texto hay en temp.txt, podría pasar a una solución perl.
user17591

Respuestas:

34

Lo que ha hecho es eliminar SUBSTITUTETHISdonde aparece en el archivo (pero no el resto de la línea donde aparece) e insertar el contenido temp.TXTdebajo de esa línea. Si SUBSTITUTETHISaparece varias veces en una línea, solo se elimina la primera aparición y solo temp.TXTse agrega una copia de .

Si desea reemplazar la línea completa cuando SUBSTITUTETHISaparece, use el dcomando. Dado que necesita ejecutar ambos ry dcuando haya una coincidencia, colóquelos en un grupo de refuerzo.

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

Algunas implementaciones sed le permiten usar punto y coma para separar comandos y omitir separadores por completo entre llaves, pero aún necesita una nueva línea para terminar el argumento del rcomando:

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

Si desea reemplazar SUBSTITUTETHISpor el contenido del archivo, pero conserva lo que viene antes y después en la línea, es más complicado. El método más simple es incluir el contenido del archivo en el comando sed; tenga en cuenta que deberá citar correctamente su contenido.

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

O usa Perl. Esto es breve pero se ejecuta catuna vez para cada sustitución:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

Para leer el archivo una vez cuando se inicia el script y evitar depender de un comando de shell:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

(presentado en dos líneas para facilitar la lectura, pero puede omitir el salto de línea). Si el nombre del archivo es variable, para evitar problemas de citas, páselo al script a través de una variable de entorno:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt
Gilles 'SO- deja de ser malvado'
fuente
¿Cómo podría cambiar el comando perl para que en lugar de cat temp.txtpoder hacerlo cat ${variable}?
Maria Ines Parnisari
@MariaInesParnisari Cometí un error al formatear los comentarios. Vea mi respuesta, con una solución ligeramente diferente y más robusta.
Gilles 'SO- deja de ser malvado'
Dado que File :: Slurp no siempre está instalado, una alternativa es usar el -0777interruptor para slurp en todo el archivo, y un regular open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk
Cómo r temp.TXTfinalizar con mensajes como "BEGIN temp.TXT", "END temp.TXX"
kyb
Encontré solución para mi pregunta. Usar a(agregar) comando. grymoire.com/Unix/Sed.html#uh-36
kyb