我有一个包含分段数据的配置文件,如下所述。使用 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
但是,我无法找出列出单个部分的方法。