Если у вас есть доступный 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" )