使用sed / awk从ini样式文件中读取值

时间:2016-06-16 19:45:40

标签: bash awk sed ini

我写了一个简单的bash函数,它将从ini文件中读取值(由变量CONF_FILE定义)并输出

getConfValue() {
 #getConfValue section variable
 #return value of a specific variable from given section of a conf file
 section=$1
 var="$2"
 val=$(sed -nr "/\[$section\]/,/\[/{/$var/p}" $CONF_FILE)
 val=${val#$var=}
 echo "$val"
}

问题在于,如果节名称中的多个变量共享公共子串,它不会忽略注释并遇到麻烦。

示例ini文件:

[general]
# TEST=old
; TEST=comment  
TEST=new
TESTING=this will be output too
PATH=/tmp/test

正在运行getConfValue general PATH会按预期输出/tmp/test,但正在运行getConfValue general TEST会显示此方法存在的所有问题。

如何解决这个问题?

我知道有一些像crudini这样的专用工具或python,perl和php的工具,但是我不希望为简单的配置文件解析添加额外的依赖项。结合awk而不是sed的解决方案也可以。

1 个答案:

答案 0 :(得分:6)

坚持使用sed,您可以使用var^搜索锚定到记录的开头,并以等号结束:

"/\[$section\]/,/\[/{/^$var=/p}"

如果您担心记录前面的空白,可以说明这一点:

"/\[$section\]/,/\[/{/^(\W|)$var=/p}"

^(\W|)$var=在您的变量与等号(^(\W)连接之前,表示“如果开头有空格(|))或没有任何内容($var=)。 “

如果您想切换到awk,可以使用以下内容:

val=$(awk -F"=" -v section=$section -v var=$var '$1=="["section"]"{secFound=1}secFound==1 && $1==var{print $2; secFound=0}' $CONF_FILE)

awk命令将记录拆分为-F"="。然后,如果记录中的第一个字段是您的部分($1=="["section"]"),则将变量secFound设置为1.然后......如果secFound为1且第一个字段完全等于您的var变量(secFound==1 && $1==var)然后打印出第二个字段({print $2})并将secFound设置为0,这样我们就不会选择任何其他Test个键