Если у вас есть доступный Git и вы согласны с ограничением невозможности использовать подчеркивания в именах ключей, вы можете использовать его git config
как синтаксический анализатор / редактор INI общего назначения.
Он будет обрабатывать разбор пары ключ / значение по всему =
и отбрасывать незначительные пробелы, плюс вы получите комментарии (как ;
и #
), так и приведение типов в основном бесплатно. Я включил полный рабочий пример для ввода ОП .ini
и желаемого вывода (ассоциативные массивы Bash) ниже.
Тем не менее, учитывая конфигурационный файл, как это
; mytool.ini
[section1]
inputdir = ~/some/dir
enablesomefeature = true
enablesomeotherfeature = yes
greeting = Bonjour, Monde!
[section2]
anothersetting = 42
… Если вам просто нужно быстрое и грязное решение, и вы не женаты на идее иметь настройки в ассоциативном массиве Bash, вы можете получить всего лишь:
eval $(git config -f mytool.ini --list | tr . _)
# or if 'eval' skeeves you out excessively
source <(git config -f mytool.ini --list | tr . _)
который создает переменные среды с именами sectionname_variablename
в текущей среде. Это, конечно, работает, только если вы можете верить, что ни одно из ваших значений никогда не будет содержать точку или пробел (более подробное решение см. Ниже).
Другие простые примеры
Извлечение произвольных значений с использованием функции оболочки для сохранения ввода:
function myini() { git config -f mytool.ini; }
Псевдоним тоже будет в порядке, но он обычно не раскрывается в сценарии оболочки [ 1 ], и в любом случае псевдонимы заменяются функциями оболочки «почти для всех целей» [ 2 ], согласно странице руководства Bash .
myini --list
# result:
# section1.inputdir=~/some/dir
# section1.enablesomefeature=true
# section1.enablesomeotherfeature=yes
# section2.anothersetting=42
myini --get section1.inputdir
# result:
# ~/some/dir
С помощью этой --type
опции вы можете «канонизировать» определенные настройки в виде целых чисел, логических значений или путей (автоматически расширяется ~
):
myini --get --type=path section1.inputdir # value '~/some/dir'
# result:
# /home/myuser/some/dir
myini --get --type=bool section1.enablesomeotherfeature # value 'yes'
# result:
# true
Чуть более надежный, быстрый и грязный пример
Сделайте все переменные mytool.ini
доступными как SECTIONNAME_VARIABLENAME
в текущей среде, сохранив внутренний пробел в значениях ключа:
source <(
git config -f mytool.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/\U\1_\2\E="\3"/'
)
То, что делает выражение sed, на английском языке, это
- найти группу непериодических символов до периода, помня это как
\1
, затем
- найти группу символов до знака равенства, помня, что как
\2
, и
- найти все символы после знака равенства как
\3
- наконец, в строке замены
- имя раздела + имя переменной в верхнем регистре, и
- часть значения заключена в двойные кавычки, если она содержит символы, которые имеют особое значение для оболочки, если она не заключена в кавычки (например, пробел)
Последовательности \U
и \E
в строке замены (верхний регистр этой части строки замены) являются sed
расширением GNU . В macOS и BSD вы бы просто использовали несколько -e
выражений для достижения одного и того же эффекта.
Работа со встроенными кавычками и пробелами в названиях разделов (что git config
позволяет) оставляется в качестве упражнения для читателя.:)
Использование имен разделов в качестве ключей в ассоциативном массиве Bash
Данный:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
Это даст результат, который запрашивает OP, просто переставив некоторые записи в выражении замены sed, и будет работать без GNU sed:
source <(
git config -f foo.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/declare -A \2["\1"]="\3"/'
)
Я предполагаю, что при цитировании реального .ini
файла могут возникнуть некоторые проблемы , но это работает для приведенного примера. Результат:
declare -p {session,path}
# result:
# declare -A session=([barfoo]="bar" [foobar]="foo" )
# declare -A path=([barfoo]="/some/path" [foobar]="/some/path" )