Replacing variable correctly in alias function

I’m trying to create an alias function to remove inputted line from file:

function remove_line(){
       line_to_remove="'s/^"$1"$//g'"
       sed -i $(line_to_remove) my_file
}

For example:
remove_line domain.com should remove this domain from a given file.

However it seems that the $ is not interpreted correctly. What am I doing wrong?

Asked By: ellat

||

Your main issue is that $(line_to_remove) is a command substitution, i.e., an expression replaced by the text outputted by the command inside the parentheses (line_to_remove, which I would expect give you a "command not found" error). You are probably wanting to use "$line_to_remove" instead.

However, injecting a shell variable into a sed substitution expression is less than ideal as it puts too many conditions on the injected string (it has to be a valid regular expression and can’t contain /, etc.)

Instead, I suggest using grep and either writing the result to the standard output or to a temporary file that replaces the original file upon successful execution of grep, or you can let sponge (from the GNU moreutils package) overwrite the original file.

remove_lines () {
       grep -v -Fx -e "$1" my_file | sponge my_file
}

The options used with grep here ensure that the line given as the function’s first argument is used as-is (not as a regular expression), matches a line from start to end, and removes matching lines from the input.

Without sponge:

remove_lines () {
       tmpfile=$(mktemp)
       grep -v -Fx -e "$1" my_file >"$tmpfile" && mv "$tmpfile" my_file
       rm -f "$tmpfile"
}

The mv is performed only if the grep is successfully executed, and the rm -f removes the temporary file in the case that it didn’t.


Personally, I would probably write the function like this:

remove_lines () {
       grep -v -Fx -e "$1"
}

This allows a user to use it like so:

remove_lines "my line" <my_file | sponge my_file

some-command | remove_lines "bumble bee" | other-command

This makes the function work as a filter that only does what it says on the tin, i.e., it removes lines from the input and does not care what where the input is coming from or where it’s going.

Answered By: Kusalananda
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.