Mengedit file config melalui skrip bash

9

Saya sudah mencoba untuk menulis skrip bash sederhana yang akan saya gunakan untuk menginstal aplikasi dan memperbarui file konfigurasi itu. Saya mengalami kesulitan untuk mendapatkan file konfigurasi itu dimodifikasi.

# DBHost=localhost
DBName=test
# DBPassword=

ada saran bagaimana saya bisa mendapatkan modifikasi di atas seperti di bawah ini?

DBHost=localhost
DBName=database
DBPassword=password
compixtr
sumber
Saya tidak percaya kita harus menulis ekspresi reguler rawan kesalahan hanya untuk melakukan tugas yang sangat umum ini. Seharusnya ada alat yang distandarisasi seperti "update_config test.confg -uncomment_if_pressent DBHost = localhost".
bigjosh

Jawaban:

3

Cara terbaik tergantung pada apakah Anda mengharapkan file juga dimodifikasi oleh manusia, seberapa kompleks file itu, dan apakah Anda ingin skrip Anda diutamakan jika terlihat seperti orang lain menginginkan nilai yang berbeda. Artinya, jika file sudah berisi DBPassword=swordfish, apakah Anda ingin menyimpannya, atau menggantinya dengan DBPassword=password?

Cara yang umum untuk menangani ini adalah memiliki bagian file yang dibatasi oleh "komentar ajaib", dan hanya mengedit bagian di antara komentar ini. Inilah cara untuk melakukan ini dengan awk. Jika komentar ajaib tidak ada, bagian baru ditambahkan di akhir file. Peringatan: kode yang belum diuji.

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

Pendekatan ini tidak berfungsi dengan baik jika program yang membaca file konfigurasi tidak mendukung banyak baris pengaturan item konfigurasi yang sama. Dalam hal ini, Anda benar-benar harus menghapus yang lama. Dalam hal ini saya akan menyarankan agar komentar tidak tersentuh dan menambahkan pengaturan Anda sendiri di akhir.

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 'SANGAT berhenti menjadi jahat'
sumber
Apakah Anda menguji kode ini? atau masih belum teruji?
rubo77
Contoh hebat lainnya di sini: stackoverflow.com/questions/5955548/…
rubo77
2

Jika itu yang Anda butuhkan, Anda bisa melakukan sesuatu seperti

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

Ini akan menyalin asli config.fileke config.file.bakdan membuat perubahan yang diperlukan.

terdon
sumber
2

Saya akan menggunakan "ex" dalam mode diam:

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

Perintah terdon sedadalah kompak dan efisien. Tetapi interaksi "dokumen di sini" penuh dengan perintah ex dan interpolasi shell string bisa menjadi kuat. Misalnya, kata sandi dapat diganti sebagai nilai variabel shell:

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

Jika Anda menggunakan viatau vimdan Anda terbiasa dengan mode ':', menambahkan suntingan baru / lebih baik / berbeda juga cukup mudah.

Bruce Ediger
sumber
Meskipun ex sangat kuat, sulit untuk pulih dari kesalahan (misalnya ketika garis yang diharapkan hilang). Di sini Anda dapat pergi tanpa perilaku kondisional, tetapi ini tidak menggeneralisasi dengan baik.
Gilles 'SO- berhenti menjadi jahat'