Bearbeiten der Konfigurationsdatei über ein Bash-Skript

9

Ich habe versucht, ein einfaches Bash-Skript zu schreiben, mit dem ich eine Anwendung installieren und ihre Konfigurationsdatei aktualisieren werde. Es fällt mir schwer, die Konfigurationsdatei zu ändern.

# DBHost=localhost
DBName=test
# DBPassword=

Irgendwelche Vorschläge, wie ich oben wie unten modifiziert werden kann?

DBHost=localhost
DBName=database
DBPassword=password
compixtr
quelle
Ich kann nicht glauben, dass wir fehleranfällige reguläre Ausdrücke schreiben müssen, um diese sehr häufige Aufgabe zu erledigen. Es sollte wirklich ein standardisiertes Tool wie "update_config test.confg -uncomment_if_pressent DBHost = localhost" geben.
Bigjosh

Antworten:

3

Der beste Weg hängt davon ab, ob Sie erwarten, dass die Datei auch von Menschen geändert wird, wie komplex die Datei ist und ob Ihr Skript Vorrang haben soll, wenn es so aussieht, als ob jemand anderes einen anderen Wert wünscht. Das heißt, wenn die Datei bereits enthält DBPassword=swordfish, möchten Sie diese beibehalten oder durch ersetzen DBPassword=password?

Eine übliche Methode, um damit umzugehen, besteht darin, einen Abschnitt der Datei durch „magische Kommentare“ zu begrenzen und nur den Teil zwischen diesen Kommentaren zu bearbeiten. Hier ist eine Möglichkeit, dies mit awk zu tun. Wenn die magischen Kommentare nicht vorhanden sind, wird der neue Abschnitt am Ende der Datei hinzugefügt. Warnung: ungetesteter Code.

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

Dieser Ansatz funktioniert nicht gut, wenn das Programm, das die Konfigurationsdatei liest, nicht mehrere Zeilen unterstützt, die dasselbe Konfigurationselement festlegen. In diesem Fall müssen Sie die alten wirklich entfernen. In diesem Fall würde ich empfehlen, die Kommentare unberührt zu lassen und am Ende Ihre eigenen Einstellungen hinzuzufügen.

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 - hör auf böse zu sein'
quelle
Haben Sie diesen Code getestet? oder ist es noch ungetestet?
Rubo77
Andere gute Beispiele hier: stackoverflow.com/questions/5955548/…
rubo77
2

Wenn das alles ist, was Sie brauchen, können Sie so etwas tun

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

Dadurch wird das Original kopieren config.filezu config.file.bakund nehmen Sie die notwendigen Änderungen.

terdon
quelle
2

Ich werde mit "ex" im stillen Modus gehen:

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

terdons sedBefehl ist kompakt und effizient. Die Interaktion eines "Hier-Dokuments" voller Ex-Befehle und Shell-String-Interpolation kann jedoch leistungsstark sein. Beispielsweise könnte das Kennwort als Wert einer Shell-Variablen ersetzt werden:

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

Wenn Sie vioder verwenden vimund mit dem ':' - Modus vertraut sind, ist das Hinzufügen neuer / besserer / anderer Bearbeitungen ebenfalls recht einfach.

Bruce Ediger
quelle
Während ex mächtig ist, ist es schwierig, Fehler zu beheben (z. B. wenn eine erwartete Zeile fehlt). Hier kann man ohne bedingtes Verhalten davonkommen, aber das lässt sich nicht so gut verallgemeinern.
Gilles 'SO - hör auf böse zu sein'