Edycja pliku konfiguracyjnego za pomocą skryptu bash

9

Próbowałem napisać prosty skrypt bash, którego użyję do zainstalowania aplikacji i zaktualizowania jej pliku konfiguracyjnego. Mam trudności z modyfikacją pliku konfiguracyjnego.

# DBHost=localhost
DBName=test
# DBPassword=

jakieś sugestie, w jaki sposób mogę uzyskać powyżej zmodyfikowane, jak poniżej?

DBHost=localhost
DBName=database
DBPassword=password
compixtr
źródło
Nie mogę uwierzyć, że musimy napisać wyrażenia regularne podatne na błędy, aby wykonać to bardzo częste zadanie. Naprawdę powinno istnieć znormalizowane narzędzie, takie jak „update_config test.confg -uncomment_if_pressent DBHost = localhost”.
bigjosh,

Odpowiedzi:

3

Najlepszy sposób zależy od tego, czy spodziewasz się, że plik zostanie również zmodyfikowany przez ludzi, jak skomplikowany jest plik i czy chcesz, aby twój skrypt miał pierwszeństwo, jeśli wygląda na to, że ktoś inny chce innej wartości. To znaczy, jeśli plik już zawiera DBPassword=swordfish, czy chcesz to zachować, czy zastąpić DBPassword=password?

Częstym sposobem radzenia sobie z tym jest oddzielenie części pliku „magicznymi komentarzami” i edytowanie tylko części między tymi komentarzami. Oto sposób na zrobienie tego za pomocą awk. Jeśli magiczne komentarze nie są obecne, nowa sekcja jest dodawana na końcu pliku. Ostrzeżenie: nieprzetestowany kod.

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

To podejście nie działa dobrze, jeśli program odczytujący plik konfiguracyjny nie obsługuje wielu wierszy ustawiających ten sam element konfiguracji. W takim przypadku naprawdę musisz usunąć stare. W takim przypadku radzę pozostawić komentarze nietknięte i dodać własne ustawienia na końcu.

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- przestań być zły”
źródło
Czy przetestowałeś ten kod? czy jest jeszcze nie przetestowany?
rubo77
Inne świetne przykłady tutaj: stackoverflow.com/questions/5955548/…
rubo77
2

Jeśli to wszystko, czego potrzebujesz, możesz zrobić coś takiego

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

Spowoduje to skopiowanie oryginału config.filedo config.file.baki dokonać niezbędnych zmian.

terdon
źródło
2

Pójdę z „ex” w trybie cichym:

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

Komenda terdona sedjest zwarta i wydajna. Ale interakcja „dokumentu tutaj” pełnego poleceń ex i interpolacji ciągów powłoki może być potężna. Na przykład hasło można zastąpić wartością zmiennej powłoki:

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

Jeśli używasz vilub vimznasz tryb „:”, dodawanie nowych / lepszych / różnych edycji jest również dość łatwe.

Bruce Ediger
źródło
Chociaż ex jest potężny, trudno jest go naprawić po błędach (np. Gdy brakuje oczekiwanej linii). Tutaj możesz uciec bez żadnego zachowania warunkowego, ale nie uogólnia to tak dobrze.
Gilles „SO- przestań być zły”