Редагування конфігураційного файлу за допомогою сценарію bash


9

Я намагався написати простий скрипт bash, який я буду використовувати для встановлення програми та оновлення конфігураційного файлу. Мені важко отримати його змінений файл конфігурації.

# DBHost=localhost
DBName=test
# DBPassword=

будь-які пропозиції, як я можу отримати вище модифікований як нижче?

DBHost=localhost
DBName=database
DBPassword=password

Я не можу повірити, що нам доведеться писати регулярні вирази, схильні до помилок, просто для цього дуже поширеного завдання. Справді має бути стандартизований інструмент на зразок "update_config test.confg -uncomment_if_pressent DBHost = localhost".
bigjosh

Відповіді:


3

Найкращий спосіб залежить від того, чи очікуєте ви, що файл також буде модифікований людьми, наскільки складний файл і чи хочете, щоб ваш сценарій мав перевагу, якщо він схожий на те, що хтось інший хоче іншого значення. Тобто, якщо файл вже містить 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

Ви перевірили цей код? чи це все ще неперевірено?
rubo77

Інші великі приклади тут: stackoverflow.com/questions/5955548 / ...
rubo77

2

Якщо це все, що вам потрібно, ви можете зробити щось подібне

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

Це буде копіювати оригінал , config.fileщоб config.file.bakі внести необхідні зміни.


2

Я перейду з "колишнім" в беззвучному режимі:

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

Команда тердона sedє компактною та ефективною. Але взаємодія "тут документа", наповненого екс-командами та інтерполяцією рядкових оболонок, може бути потужною. Наприклад, пароль можна замінити як значення змінної оболонки:

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

Якщо ви користуєтесь режимом ':' viабо vimвам знайомий, додавання нових / кращих / різних змін також є досить простим.


Хоча екс є потужним, важко відновитись після помилок (наприклад, коли очікуваний рядок відсутній). Тут можна піти без будь-якої умовної поведінки, але це не так узагальнюється.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.