从配置文件访问分段变量

从配置文件访问分段变量

我有一个包含分段数据的配置文件,如下所述。使用 shell 脚本访问每个变量。我正在使用 sed 命令来实现这一点,现在我面临一个问题,比如如果我忘记配置一个变量示例:名称 [APP1] 它将采用 [APP2] 名称。
配置文件:

[APP1]
name=Application1
StatusScript=/home/status_APP1.sh
startScript=/home/start_APP1.sh
stopScript=/home/stop_APP1.sh
restartScript=/home/restart.APP1.sh

[APP2]
name=Application2
StatusScript=/home/status_APP2.sh
startScript=/home/start_APP2.sh
stopScript=/home/stop_APP2.sh
restartScript=/home/restart.APP2.sh
logdir=/log/APP2/
.
.
.
.
.
[APPN]
name=ApplicationN
StatusScript=/home/status_APPN.sh
startScript=/home/start_APPN.sh
stopScript=/home/stop_APPN.sh
restartScript=/home/restart.APPN.sh
logdir=/log/APPN

shell 命令使用:

sed -nr "/^\[APP1\]/ { :l /^name[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}"

有没有办法解决这个问题,如果某个部分下没有配置某个变量,则通过 null 或 0 作为变量值。

答案1

将您的配置解析为明确的格式,然后将其读入最新版本的关联数组中bash

awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf

这会找到所有节标题并将awk变量设置app为这些节标题的内容。然后,它在接下来的每一行前面加上该值,后跟一个点。

这将创建类似的输出

APP1.name=Application1
APP1.StatusScript=/home/status_APP1.sh
APP1.startScript=/home/start_APP1.sh
APP1.stopScript=/home/stop_APP1.sh
APP1.restartScript=/home/restart.APP1.sh
APP2.name=Application2
APP2.StatusScript=/home/status_APP2.sh
APP2.startScript=/home/start_APP2.sh
APP2.stopScript=/home/stop_APP2.sh
APP2.restartScript=/home/restart.APP2.sh
APP2.logdir=/log/APP2/

如果您APP2缺少一个name小节,则该APP2.name行将不会显示。

然后将其读入关联数组中bash

declare -A conf
while IFS='=' read -r key value; do
    conf[$key]="$value"
done < <(awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf)

您现在可以查询conf您的配置的变量:

printf 'The stopScript for APPN is "%s"\n' "${conf[APPN.stopScript]}"

这将返回

The stopScript for APPN is "/home/stop_APPN.sh"

查询不存在的值将产生空字符串。


awk命令也可以替换为以下sed命令:

sed -n \
    -e '/^\[/{s/[][]//g;h;}' \
    -e '/=/{H;g;s/\n/./;p;s/\..*//;h;}' file.conf

扩展并注释:

/^\[/{          # handle section headers
    s/[][]//g;  # remove [ and ]
    h;          # put into the hold-space
}

/=/{            # handle settings
    H;          # append the line to the hold-space with newline as delimiter
    g;          # get the hold-space
    s/\n/./;    # replace the newline with a dot
    p;          # output
    s/\..*//;   # remove everything after the dot
    h;          # put back into the hold-space
}

答案2

您可以创建一个像这样的 shell 函数:

printSection()
{
  section="$1"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    echo "$line"
  done
}

然后,您可以像命令一样使用 printSection ,并将该部分作为参数传递,如下所示:

printSection APP2

要获取参数,您现在可以使用更简单的 sed,例如:

printSection APP2 | sed -n 's/^name=//p'

这将在标准输入上运行并写入标准输出。因此,如果您的示例配置文件名为 /etc/application.conf,并且您想将 APP2 的名称存储在变量 app2name 中,您可以这样写:

app2name=$(printSection APP2 | sed -n 's/^name//p/' < /etc/applications.conf)

或者,您可以将参数部分构建到函数中并完全跳过 sed,如下所示:

printValue()
{
  section="$1"
  param="$2"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    [[ "${line%=*}" == "$param" ]] && { echo "${line#*=}"; break; }
  done
}

然后你可以像这样分配你的变量:

app2name=$(printValue APP2 name < /etc/applications.conf)

答案3

如果您有权访问 Git,则可以“滥用”其config功能来查询配置文件:

git config --file /etc/applications.cfg --get APPN.stopScript

您还可以使用参数以section.key=value格式列出所有键/值对--list

git config --file /etc/applications.cfg --list

但是,我无法找出列出单个部分的方法。

相关内容