
Estoy intentando crear una función de alias para eliminar la línea ingresada del archivo:
function remove_line(){
line_to_remove="'s/^"$1"$//g'"
sed -i $(line_to_remove) my_file
}
Por ejemplo:
remove_line domain.com
debería eliminar este dominio de un archivo determinado.
Sin embargo parece que $
no se interpreta correctamente. ¿Qué estoy haciendo mal?
Respuesta1
Su principal problema es que $(line_to_remove)
es unsustitución de comando, es decir, una expresión reemplazada por el texto generado por el comando dentro del paréntesis ( line_to_remove
, que esperaría que le dé un error de "comando no encontrado"). Probablemente quieras utilizarlo "$line_to_remove"
en su lugar.
Sin embargo, inyectar una variable de shell en una sed
expresión de sustitución no es ideal ya que impone demasiadas condiciones a la cadena inyectada (tiene que ser una expresión regular válida y no puede contener /
, etc.)
En su lugar, sugiero usar grep
y escribir el resultado en la salida estándar o en un archivo temporal que reemplace el archivo original tras la ejecución exitosa de grep
, o puede permitir sponge
(desde el paquete GNU moreutils) sobrescribir el archivo original.
remove_lines () {
grep -v -Fx -e "$1" my_file | sponge my_file
}
Las opciones utilizadas grep
aquí garantizan que la línea proporcionada como primer argumento de la función se utilice tal cual (no como una expresión regular), coincida con una línea de principio a fin y elimine las líneas coincidentes de la entrada.
Sin sponge
:
remove_lines () {
tmpfile=$(mktemp)
grep -v -Fx -e "$1" my_file >"$tmpfile" && mv "$tmpfile" my_file
rm -f "$tmpfile"
}
Se mv
realiza solo si grep
se ejecuta correctamente y rm -f
elimina el archivo temporal en caso de que no sea así.
Personalmente, probablemente escribiría la función así:
remove_lines () {
grep -v -Fx -e "$1"
}
Esto permite al usuario usarlo así:
remove_lines "my line" <my_file | sponge my_file
some-command | remove_lines "bumble bee" | other-command
Esto hace que la función funcione como un filtro quesolo hace lo que dice en la lata, es decir, elimina líneas de la entrada y no le importa de dónde viene la entrada ni hacia dónde va.