
Estou tentando criar uma função de alias para remover a linha inserida do arquivo:
function remove_line(){
line_to_remove="'s/^"$1"$//g'"
sed -i $(line_to_remove) my_file
}
Por exemplo:
remove_line domain.com
deve remover este domínio de um determinado arquivo.
No entanto, parece que o $
não é interpretado corretamente. O que estou fazendo de errado?
Responder1
Seu principal problema é que $(line_to_remove)
é umsubstituição de comando, ou seja, uma expressão substituída pelo texto gerado pelo comando entre parênteses ( line_to_remove
, que eu esperaria que gerasse um erro de "comando não encontrado"). Você provavelmente está querendo usar "$line_to_remove"
.
No entanto, injetar uma variável shell em uma sed
expressão de substituição não é o ideal, pois coloca muitas condições na string injetada (ela deve ser uma expressão regular válida e não pode conter /
etc.)
Em vez disso, sugiro usar grep
e gravar o resultado na saída padrão ou em um arquivo temporário que substitua o arquivo original após a execução bem-sucedida de grep
, ou você pode deixar sponge
(do pacote GNU moreutils) sobrescrever o arquivo original.
remove_lines () {
grep -v -Fx -e "$1" my_file | sponge my_file
}
As opções usadas grep
aqui garantem que a linha fornecida como primeiro argumento da função seja usada como está (não como uma expressão regular), corresponda a uma linha do início ao fim e remova as linhas correspondentes da entrada.
Sem sponge
:
remove_lines () {
tmpfile=$(mktemp)
grep -v -Fx -e "$1" my_file >"$tmpfile" && mv "$tmpfile" my_file
rm -f "$tmpfile"
}
O mv
é executado somente se grep
for executado com sucesso e rm -f
remove o arquivo temporário caso isso não aconteça.
Pessoalmente, eu provavelmente escreveria a função assim:
remove_lines () {
grep -v -Fx -e "$1"
}
Isso permite que um usuário use-o assim:
remove_lines "my line" <my_file | sponge my_file
some-command | remove_lines "bumble bee" | other-command
Isso faz com que a função funcione como um filtro quesó faz o que diz na lata, ou seja, ele remove linhas da entrada e não se importa de onde a entrada vem ou para onde está indo.