Найкращий спосіб залежить від того, чи очікуєте ви, що файл також буде модифікований людьми, наскільки складний файл і чи хочете, щоб ваш сценарій мав перевагу, якщо він схожий на те, що хтось інший хоче іншого значення. Тобто, якщо файл вже містить DBPassword=swordfish
, ви хочете зберегти це чи замінити його DBPassword=password
?
Поширений спосіб вирішення цього питання полягає в тому, щоб розділ файлу був розділений "магічними коментарями" і редагував лише частину між цими коментарями. Ось спосіб зробити це з awk. Якщо чарівних коментарів немає, новий розділ додається в кінці файлу. Попередження: неперевірений код.
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
Цей підхід не працює добре, якщо програма, яка читає файл конфігурації, не підтримує кілька рядків, що встановлюють один і той же елемент конфігурації. У такому випадку вам справді потрібно буде видалити старі. У такому випадку я б радив залишити коментарі недоторканими та додати свої власні налаштування наприкінці.
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