¿Cómo usar sed para escribir en un nombre de archivo almacenado en una variable?

¿Cómo usar sed para escribir en un nombre de archivo almacenado en una variable?

Desde dentro de un bashscript, ¿cómo puedo sedescribir en un archivo donde el nombre del archivo está almacenado en una variable bash? La redirección de salida no funciona porque quiero editar un archivo en su lugar, extrayendo líneas que coincidan con una expresión regular en un archivo diferente y eliminándolas en el primer archivo.

Algo como:

sed -i '/^my regex here$/{;w file2;d;}' file1

... pero ¿dónde file1y file2están ambos en realidad?variablesesosostenerlos nombres de archivos. (Como file2=$(mktemp).)

Entonces, lo que realmente quiero es una expansión variable para el nombre del archivo, pero ninguna expansión para el resto del sedcomando, y dejar todo como un único argumento pasado al sedcomando.

Por alguna razón, lo siguiente no funciona:

sed -i '/my regex here/{;w '"$file2"';d;}' $file1

Dice "incomparable {" y no veo por qué.

¿Alguna forma de hacer esto?

Respuesta1

Debido a que estás usando una sola sedexpresión, todo lo que sigue después de w(incluido }) esinterpretado como elarchivo wnombre:

El argumento wfilefinalizará el comando de edición.

Puedes ver eso si agregas un segundo comando, }por ejemplo, como:

sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1

luego, las líneas que coincidan my regex herese guardarán en un archivo llamado whatever;d;}donde whateverestá lo que $file1se expande.
La sintaxis correcta es mediante comandos separados, o bien con varias expresiones:

sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2

o un comando por línea:

sed '/my regex here/{
w '"$file1"'
d
}
' $file2

Respuesta2

Encontré la respuesta enDesbordamiento de pilaen "¿Cómo hago para que el comando sed 'w' sepa dónde termina el nombre del archivo?"

Como señaló Terdon, el problema no es la variable, pero tampoco tiene nada que ver con las llaves; Pruébelo sed '/^l/w testing;p'y verá que no arroja ningún error, pero escribe todas las líneas que comienzan con a len un archivo llamado testing;p.

En realidad, el problema es la falta de una nueva línea después del nombre del archivo.

Entonces la respuesta es usar una nueva línea en línea en el comando sed:

sed -i '/my regex here/{;w '"$file2"'
d;}' $file1

O, lo que es mucho más limpio, utiliza dos -eargumentos separados:

sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1

Si no le gustan las dos comillas adyacentes (que podría pasar fácilmente por alto), simplemente coloque el comando de escritura en su propio argumento:

sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1

Respuesta3

Utilice comillas dobles en lugar de las simples para citar el comando sed. Y no olvides escapar de los personajes adecuados.

Más información sobre citar variables en bash en esteenlace

información relacionada