如何parsing和转换ini文件到bash数组variables?

我试图将一个ini文件转换成bash数组variables。 样本ini如下所示:

[foobar] session=foo path=/some/path [barfoo] session=bar path=/some/path 

所以这些成为:

 session[foobar]=foo path[foobar]=/some/path session[barfoo]=bar 

等等。

现在,我只能拿出这个命令

 awk -F'=' '{ if ($1 ~ /^\[/) section=$1; else if ($1 !~ /^$/) print $1 section "=" $2 }' 

另外,还有一个问题是,它不会考虑到附近的空间。 我认为sed可能更适合这个工作,但我不知道如何在sed保存和存储一个用于部分名称的临时variables。

那么任何想法如何做到这一点?

Gawk接受正则expression式作为字段分隔符。 以下消除了等号周围的空格,但在行的其余部分保留了它们。 在值周围添加引号,以便在执行Bash分配时保留这些空格(如果有的话)。 我假定段名称是数字variables,但是如果你使用的是Bash 4,可以很容易地使用它来使用关联数组和段名称本身作为索引。

 awk -F ' *= *' '{ if ($1 ~ /^\[/) section=$1; else if ($1 !~ /^$/) print $1 section "=" "\"" $2 "\"" }' 

请注意,由于Bashvariables名称不能包含空格,因此您可能还想要执行Khaled显示的空间删除(仅限$ 1和部分)。

另外,如果值包含等号,则此方法将不起作用。

另一种技术是while read循环时使用Bash, while read文件时使用declare来执行分配, declare对大多数恶意内容是安全的。

 foobar=1 barfoo=2 # or you could increment an index variable each time a section is found while IFS='= ' read var val do if [[ $var == \[*] ]] then section=$var elif [[ $val ]] then declare "$var$section=$val" fi done < filename 

同样,关联数组可以很容易地被支持。

我将使用简单的Python脚本来完成这项工作,因为它已经内置在INI 分析器中 :

 #!/usr/bin/env python import sys, ConfigParser config = ConfigParser.ConfigParser() config.readfp(sys.stdin) for sec in config.sections(): print "declare -A %s" % (sec) for key, val in config.items(sec): print '%s[%s]="%s"' % (sec, key, val) 

然后在bash中:

 #!/bin/bash # load the in.ini INI file to current BASH - quoted to preserve line breaks eval "$(cat in.ini | ./ini2arr.py)" # test it: echo ${barfoo[session]} 

当然,在awk中有更短的实现,但我认为这是更易读,更容易维护。

如果你想消除额外的空间,你可以使用内置的函数gsub 。 例如,您可以添加:

 gsub(/ /, "", $1); 

这将删除所有的空间。 如果要删除标记开头或结尾的空格,可以使用

 gsub(/^ /, "", $1); gsub(/ $/, "", $1); 

这是一个纯粹的bash解决scheme。

这是chilladx发布的新的改进版本:

https://github.com/albfan/bash-ini-parser

对于一个非常容易遵循的初始示例:下载完成后,只需将文件bash-ini-parserscripts/file.ini到同一目录中,然后使用下面提供的示例创build客户端testing脚本同样的目录。

 source ./bash-ini-parser cfg_parser "./file.ini" cfg_section_sec2 echo "var2=$var2" echo "var5[*]=${var5[*]}" echo "var5[1]=${var5[1]}" 

这是我对bash-ini-parser脚本进行的一些改进。

如果你想能够读取带有Windows行尾的ini文件以及Unix,那么在读取该文件的那一行之后,立即将这一行添加到cfg_parser函数中:

 ini=$(echo "$ini"|tr -d '\r') # remove carriage returns 

如果要读取具有限制性访问权限的文件,请添加以下可选function:

 # Enable the cfg_parser to read "locked" files function sudo_cfg_parser { # Get the file argument file=$1 # If not "root", enable the "sudo" prefix sudoPrefix= if [[ $EUID -ne 0 ]]; then sudoPrefix=sudo; fi # Save the file permissions, then "unlock" the file saved_permissions=$($sudoPrefix stat -c %a $file) $sudoPrefix chmod 777 $file # Call the standard cfg_parser function cfg_parser $file # Restore the original permissions $sudoPrefix chmod $saved_permissions $file }