LINUX.ORG.RU

Функция для чтения INI-файлов

 


1

1

См. https://github.com/DRVTiny/bash4-debug-infra/blob/master/config.func
Пользоваться так:

eval "$(read_ini /PATH/TO/INI)"

В результате для конфиг-файла вида:

[global]
USER_HOME={{getent passwd myuser | cut -d: -f6}}
BIN_DIR={{global.USER_HOME}}/bin

[checker]
SHELL_SCRIPT={{global.BIN_DIR}}/checker.sh
имеем на выходе:
INIglobal[USER_HOME]="/home/myuser"
INIglobal[BIN_DIR]="/home/myuser/bin"
INIchecker[SHELL_SCRIPT]="/home/myuser/bin/checker.sh"

В чём профит по сравнению с просто source кода на BASH:
1) Языкоиндифферентность самого конфиг-файла. Без использования макропеременных внутри INI-файла можно будет читать его уже разработанными функциями для других языков программирования.
С использованием макропеременных ввиду их нестандартности для INI-формата, нужно реализовать их подстановку на любом удобном для вас языке (на Perl это делается элементарно).
2) INI-файл структурирован, уникальность имён переменных обязательна только в пределах одной секции, что весьма удобно для действительно больших конфиг-файлов

P.S.Разумеется, работает только на BASH4. Если вы до сих пор пользуетесь BASH3 - убейте себя об стену.

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 3)

Ничего так. А парсер JSON под баш есть? Ещё более структурированно, языкоиндифферентно, универсально и заставляет пользователей древнего уг убиваться об стену ещё сильнее.

border-radius
()
Ответ на: комментарий от border-radius

А парсер JSON под баш есть?

Вполне, возможно, раз есть даже log4sh
Мне не нужно - я не писал.

DRVTiny ★★★★★
() автор топика

Интересное наблюдение:

В велосипедостроении часто встречается забивание гвоздей микроскопом. А на bash'е в основном наоборот - выполняют ювелирные работы при помощи кувалды 8).

Deleted
()

Bash? NOWAY.

> cat 08-conf
parse_ini()
{
sed -e 's@[^M]@@g;'"s@'@'\"'\"'@g" $1 | \]@@g;'"s@'@'\"'\"'@g" $1 | \
(
SECTION=""
while read line; do
        case $line in
                \[*\]) # SECTION
                        SECTION=${line/\[/}
                        SECTION=${SECTION/]/}
                ;;
                *=*) # KEY=VALUE
                        KEY=${line/=*/}
                        VALUE=${line/*=/}
                        echo "${SECTION}_${KEY}='${VALUE}'"
                        LOADED_KEYS="${LOADED_KEYS} ${SECTION}_${KEY}"
                ;;
        esac
done
echo LOADED_KEYS="\"${LOADED_KEYS}\""
unset SECTION KEY VALUE
)
}

echo "Input: "
cat test
eval $(parse_ini test)

echo "Output: "
for key in $LOADED_KEYS; do
	eval "echo $key=\$$key"
done
> sh 08-conf 
Input: 
[global]
USER_HOME={{getent passwd myuser | cut -d: -f6}}
BIN_DIR={{global.USER_HOME}}/bin

[checker]
SHELL_SCRIPT={{global.BIN_DIR}}/checker.sh
Output: 
global_USER_HOME={{getent passwd myuser | cut -d: -f6}}
global_BIN_DIR={{global.USER_HOME}}/bin
checker_SHELL_SCRIPT={{global.BIN_DIR}}/checker.sh
vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

В принципе как-то работает, но код не слишком профессионален ИМХО.
А если нужно хотя бы просто вывести на экран переменные одной секции? Не понимаю, что мешает пользоваться hash-массивами, если они есть в языке? Макроподстановок тоже нет, хотя они в общем могут быть весьма полезны и легко расширяться новым функционалом.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

В принципе как-то работает

Кое-как работает, в тривиальных случаях типа приведенного примера, да.

но код не слишком профессионален ИМХО.

Профессиональный код на sh? :D

Не понимаю, что мешает пользоваться hash-массивами, если они есть в языке

Например, отсутствие баша :)

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

Например, отсутствие баша :)

У меня он даже под виндой был, и под ним скрипты работали. На винде, заметьте, работали! Я его притащил в таком маленьком архивчике, где один только BASH, чуток утилит (split, merge, cut, sed...) и библиотеки из cygwin'а.
Никто же не говорит, что вот, мол, ваш сайт у нас работать не будет, потому что к апачу и нджинксу нет пыха, извините. Или там: ваша Perl'овая каша не сварится, потому что Perl'а нет и не будет.
BASH работает на абсолютном большинстве платформ, но где-то он есть в стандартной поставке и юзается как основной shell, а где-то нет. Точно так же там, где нужен Redmine, не всегда найдётся Ruby on Rails. Ну и что с того?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Ну, лично я предпочитаю иметь один бизибокс, если это возможно. Впрочем, думаю скоро и от него избавлюсь, в пользу коцаного systemd.

vasily_pupkin ★★★★★
()
Ответ на: комментарий от Sectoid

Рад, что оказалось интересно. Прямо даже комменты в коде захотелось писать, настолько приятно! :) :)

DRVTiny ★★★★★
() автор топика

забавно, да. иногда может оказатся полезным. хотя ini файлы - уг ещё то.

интересно, если ли такой инструмент для bash, который позволяет парсить грамматикой, заданой из командной строки?

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

хотя ini файлы - уг ещё то.

Для конфигов невыского уровня вложености — самое оно, имхо. А глубокая вложеность нужна нечасто, и, уж явно не на bash'е (хотя наверняка сейчас кто-то найдет исключение)

Sectoid ★★★★★
()
Ответ на: комментарий от DRVTiny

Рад, что оказалось интересно. Прямо даже комменты в коде захотелось писать, настолько приятно! :) :)

Сходу вопрос: поддерживается только bash4? или и другие версии (другие шеллы)?

Sectoid ★★★★★
()

Это чё за бред?

Чтение ключа в заданной секции делается на sh/sed/grep в несколько строк. И ещё в несколько строк - запись.

Да уж, былокодер - это карма...

anonymous
()
Ответ на: комментарий от nanoolinux

На BASH можно написать все, что угодно, с т.з. средств языка он не особо ограничен. Нивелирует ценность такого рода сложных алгоритмов на bash скорость исполнения кода: не могу говорить за все языки, но их тех, что известны мне, он точно самый медленный. Поэтому на нем имеет смысл реализация только достаточно простых вещей, остальные конечно лучше писать на Perl, Ruby или python

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Sectoid

поддерживается только bash4?

По сути read_ini - это компилятор INI-файла со встроенными макроподстановками в набор ассоциативных массивов BASH. Поскольку ассоциативные массивы появились только в BASH4, а раньше их эмулировали дико тормозным и часто дающим весьма неожиданные результаты методом eval, - то поддерживается только BASH версии >=4.
Был бы очень признателен тому человеку, который сделает реализацию на zsh.

DRVTiny ★★★★★
() автор топика

гы, а чем твой конфиг-файл лучше того, что «имеем на выходе»?

К тому же, «Димон, что за балет»? Где обратная операция по сборке и записи конфига?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.