Editando o arquivo de configuração através de um script bash

9

Eu tenho tentado escrever um script bash simples que eu vou usar para instalar um aplicativo e atualizar seu arquivo de configuração. Estou tendo dificuldade para obter o arquivo de configuração modificado.

# DBHost=localhost
DBName=test
# DBPassword=

alguma sugestão como eu posso ficar acima modificado como abaixo?

DBHost=localhost
DBName=database
DBPassword=password
compixtr
fonte
Não acredito que precisamos escrever expressões regulares propensas a erros apenas para executar esta tarefa muito comum. Realmente deve haver uma ferramenta padronizada como "update_config test.confg -uncomment_if_pressent DBHost = localhost".
bigjosh

Respostas:

3

A melhor maneira depende se você espera que o arquivo também seja modificado por humanos, quão complexo é o arquivo e se você deseja que seu script tenha precedência se parecer que alguém quer um valor diferente. Ou seja, se o arquivo já contiver DBPassword=swordfish, você deseja mantê-lo ou substituí-lo por DBPassword=password?

Uma maneira comum de lidar com isso é delimitar uma seção do arquivo por “comentários mágicos” e editar apenas a parte entre esses comentários. Aqui está uma maneira de fazer isso com o awk. Se os comentários mágicos não estiverem presentes, a nova seção será adicionada no final do arquivo. Aviso: código não testado.

begin_marker='# BEGIN AUTOMATICALLY EDITED PART, DO NOT EDIT'
end_marker='# END AUTOMATICALLY EDITED PART'
new_section='DBHost=localhost
DBName=database
DBPassword=password'
export begin_marker end_marker
awk <file.conf >file.conf.new -v begin_marker="$begin_marker" -v begin_marker="$end_marker" -v new_section="$new_section" '
    1 {print}
    $0 == begin_marker && !changed {
        do {getline} while ($0 != end_marker); # discard old section content
        print new_section;
        print;
        changed = 1;
    }
    END {if (!changed) {print begin_marker; print new_section; print end_marker;}}
'
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf

Essa abordagem não funciona bem se o programa que lê o arquivo de configuração não suportar várias linhas definindo o mesmo item de configuração. Nesse caso, você realmente precisará remover os antigos. Nesse caso, aconselho deixar os comentários intocados e adicionar suas próprias configurações no final.

grep -vE '^[[:blank:]]*(DBHost|DBName|DBPassword)=$' <file.conf >file.conf.new
cat <<EOF >>file.conf.new
DBHost=localhost
DBName=database
DBPassword=password
EOF
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf
Gilles 'SO- parar de ser mau'
fonte
Você testou esse código? ou ainda não foi testado?
rubo77
Outros grandes exemplos aqui: stackoverflow.com/questions/5955548/...
rubo77
2

Se isso é tudo que você precisa, você pode fazer algo como

sed  -i.bak -e 's/DBName=.*/DBName=database/' \
 -e 's/#* *DBHost=.*/DBHost=localhost/' \
 -e 's/#* *DBPassword=.*/DBPassword=password/' config.file

Isto irá copiar o original config.filepara config.file.bake fazer as mudanças necessárias.

terdon
fonte
2

Eu vou com "ex" no modo silencioso:

ex -s $CONFIG_FILE << END_CMDS
%s/^#.DBHost/DBHOST/
%s/DBName=test/DBName=database/
%s/^#.DBPassword/DBPassword/
w!
q
END_CMDS

O sedcomando de Terdon é compacto e eficiente. Mas a interação de um "documento aqui" cheio de comandos ex e interpolação de string de shell pode ser poderosa. Por exemplo, a senha pode ser substituída como o valor de uma variável do shell:

%s/^#.DBPassword=password/DBPassword=$PASSWORD/

Se você usa viou vimconhece o modo ':', adicionar edições novas / melhores / diferentes também é bastante fácil.

Bruce Ediger
fonte
Embora ex seja poderoso, é difícil se recuperar de erros (por exemplo, quando uma linha esperada está faltando). Aqui você pode fugir sem nenhum comportamento condicional, mas isso não generaliza muito bem.
Gilles 'SO- stop be evil'