Desde dentro de un bash
script, ¿cómo puedo sed
escribir 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 file1
y file2
está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 sed
comando, y dejar todo como un único argumento pasado al sed
comando.
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 sed
expresión, todo lo que sigue después de w
(incluido }
) esinterpretado como elarchivo wnombre:
El argumento
wfile
finalizará 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 here
se guardarán en un archivo llamado whatever;d;}
donde whatever
está lo que $file1
se 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 l
en 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 -e
argumentos 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