Редактирование конфигурационного файла с помощью 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компактна и эффективна. Но взаимодействие «здесь документа», полного ex-команд и интерполяции строк оболочки, может быть мощным. Например, пароль может быть заменен значением переменной оболочки:

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

Если вы используете viили vimи вы знакомы с режимом «:», добавление новых / улучшенных / различных правок также довольно просто.


Несмотря на то, что ex является мощным, его трудно восстановить после ошибок (например, когда ожидаемая строка отсутствует). Здесь вы можете уйти без какого-либо условного поведения, но это не очень хорошо обобщает.
Жиль "ТАК - перестань быть злым"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.