Reemplazar cadena con contenido de un archivo usando sed

23

Tengo dos archivos diferentes:

Archivo1

/home/user1/  
/home/user2/bin  
/home/user1/a/b/c

File2

<TEXT1>
<TEXT2>

Quiero reemplazar el <TEXT1>de File2 con el contenido de File1 usando sed. Intenté este comando, pero no obtuve el resultado adecuado:

cat File2|sed "s/<TEXT1>/$(cat File1|sed 's/\//\\\//g'|sed 's/$/\\n/g'|tr -d "\n")/g"

Puede usar otras herramientas también para resolver este problema.

chanchal1987
fuente
Pegue ese mensaje de error para que podamos localizar su fuente. También díganos qué sedimplementación está utilizando. Tu código funciona para mí con GNU sed.
manatwork
Lo sentimos, no obtengo un error. No estoy obteniendo la salida deseada. La salida es como /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. No obteniendo nuevas líneas.
chanchal1987
No estoy seguro de si esto se aplicaría en su caso específico, pero con diffy las patchherramientas permiten reemplazar algunas líneas en un archivo por otras líneas con bastante facilidad.
Stéphane Gimenez
1
Por cierto, el uso de datos aleatorios recopilados $()en un script sed hace que mis ojos sangren. Nunca use datos externos en lugares donde algunos caracteres se interpretan con un significado especial.
Stéphane Gimenez

Respuestas:

24

Aquí hay una solución de script sed (más fácil a la vista que tratar de ponerla en una línea en la línea de comando):

/<TEXT1>/ {
  r File1
  d
}

Ejecutándolo:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>
Kusalananda
fuente
Gracias, esto está funcionando. Pero no quiero usar ningún otro archivo de script. ¿Hay alguna solución en línea?
chanchal1987
Claro: sed '/<TEXT1>/{rFile1^Md^M}' File2donde "^ M" presionas volver. El problema es que sed realmente necesita las nuevas líneas dentro de {...} para delimitar los comandos r y d.
Kusalananda
66
con bash, las cuerdas de estilo posix son un poco más limpias:sed $'/<TEXT1>/ {r File1\n d}'
glenn jackman
99
También con -e para un trazador de líneas:sed -e '/<TEXT1>/{r File1' -e 'd}' File2
sdaau
1
¿Y si en lugar de reemplazar toda la línea que contiene <TEXT1>, solo quiero reemplazar la cadena en sí, dejando el resto de la línea intacta? Text1: <TEXT1>a Text1: <file_contents>.
Robin Winslow
9

Me tomó mucho tiempo encontrar esta solución usando el reemplazo de var. Todas las soluciones sed no funcionaron para mí, ya que eliminan líneas completas o las reemplazan incorrectamente.

FILE2=$(<file2)
FILE1=$(<file1)
echo "${FILE2//TEXT1/$FILE1}" 

Reemplaza todas las ocurrencias de TEXT1 en el archivo2 contra el contenido del archivo1. El resto del texto permanece intacto.

marcas756
fuente
muy agradable. posiblemente más rápido que sedtambién, ya que esas "expansiones" (también conocidas como reemplazos) están integradas en el caparazón ( bashal menos)
amarillo
7

Respondo porque el método diff/ patchpuede ser de interés en algunos casos. Para definir una sustitución de líneas contenidas en el archivo blob1por líneas contenidas en blob2uso:

diff -u blob1 blob2 > patch-file

Por ejemplo, si blob1contiene:

hello
you

y blob2contiene:

be
welcome
here

el generado patch-fileserá:

--- blob1   2011-09-08 16:42:24.000000000 +0200
+++ blob2   2011-09-08 16:50:48.000000000 +0200
@@ -1,2 +1,3 @@
-hello
-you
+be
+welcome
+here

Ahora, puede aplicar este parche a cualquier otro archivo:

patch somefile patch-file

Se reemplazará hello, youlíneas de be, welcome, herelíneas en somefile.

Stéphane Gimenez
fuente
esto es realmente inteligente, pero sería mejor si pudiera automatizar en un script
qodeninja