Правильная замена переменной в функции псевдонима

Правильная замена переменной в функции псевдонима

Я пытаюсь создать функцию-псевдоним для удаления введенной строки из файла:

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

Например: remove_line domain.comследует удалить этот домен из указанного файла.

Однако, похоже, что это $не правильно интерпретируется. Что я делаю не так?

решение1

Ваша главная проблема в том, что $(line_to_remove)этозамена команды, т. е. выражение, замененное текстом, выведенным командой внутри скобок ( line_to_remove, что, как я ожидаю, приведет к ошибке «команда не найдена»). Вероятно, вы хотите использовать "$line_to_remove"вместо этого .

Однако внедрение переменной оболочки в sedвыражение подстановки не является идеальным вариантом, поскольку накладывает слишком много условий на внедряемую строку (она должна быть допустимым регулярным выражением и не может содержать /и т. д.)

Вместо этого я предлагаю использовать grepи либо записывать результат в стандартный вывод, либо во временный файл, который заменяет исходный файл после успешного выполнения grep, либо вы можете позволить sponge(из пакета GNU moreutils) перезаписать исходный файл.

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

Параметры, используемые grepздесь, гарантируют, что строка, заданная в качестве первого аргумента функции, используется как есть (не как регулярное выражение), соответствует строке от начала до конца и удаляет соответствующие строки из входных данных.

Без sponge:

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

выполняется mvтолько в случае grepуспешного выполнения и rm -fудаляет временный файл в противном случае.


Лично я бы, наверное, написал функцию так:

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

Это позволяет пользователю использовать его следующим образом:

remove_lines "my line" <my_file | sponge my_file

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

Это заставляет функцию работать как фильтр, которыйделает только то, что написано на банке, т. е. он удаляет строки из ввода и не заботится о том, откуда поступает ввод или куда он направляется.

Связанный контент