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

Reading value from an ini style file with sed/awk

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

getConfValue() {
 #getConfValue section variable
 #return value of a specific variable from given section of a conf file
 section=
 var=""
 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 的解决方案也很好。

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

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

如果您担心记录前面的空白,您可以考虑以下原因:

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

^(\W|)$var= 表示 "if there is whitespace at the beginning (^(\W) or nothing (|)) before your variable concatenated with an equal sign ($var=)."

如果你想切换到 awk,你可以使用类似的东西:

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

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