
Я пытаюсь создать функцию-псевдоним для удаления введенной строки из файла:
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
Это заставляет функцию работать как фильтр, которыйделает только то, что написано на банке, т. е. он удаляет строки из ввода и не заботится о том, откуда поступает ввод или куда он направляется.