Reemplazo de variable correctamente en la función de alias

Reemplazo de variable correctamente en la función de alias

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.comdeberí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 sedexpresió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 grepy 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 grepaquí 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 mvrealiza solo si grepse ejecuta correctamente y rm -felimina 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.

información relacionada