如果您有可用的Git,并且可以在键名中不能使用下划线,那么可以将其git config
用作通用INI解析器/编辑器。
它将处理来自周围的键/值对的解析,=
并丢弃无关紧要的空格,此外,您还会获得注释(;
和#
),基本上免费地输入强制类型。我在下面提供了OP的输入.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
当前环境命名的环境变量。当然,只有在您可以确信所有值都不会包含句点或空格的情况下,此方法才有效(请参阅下面的更强大的解决方案)。
其他简单的例子
使用shell函数保存任意值以获取任意值:
function myini() { git config -f mytool.ini; }
同样,在这里也可以使用别名,但是别名通常不会在Shell脚本中扩展[ 1 ],并且根据Bash 手册页,别名“几乎用于所有目的”都被Shell函数所取代[ 2 ] 。
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
序列是GNU sed
扩展。在macOS和BSD上,只需使用多个-e
表达式即可达到相同的效果。
读者可以自己练习一下节名称中的嵌入引号和空格(git config
允许使用)作为练习。:)
使用节名称作为Bash关联数组的键
鉴于:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
只需通过重新排列sed替换表达式中的某些捕获,就可以产生OP要求的结果,并且在没有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" )