使用Makefile读取Yaml
问题描述:
我试图使用pkuczynski's Gist读取yaml
文件以获取key:value作为变量。使用Makefile读取Yaml
以下是我需要做的一件(多件)尝试;我没有得到任何错误,但只是一个空$(DEVURL)
:
config.yaml:
baseurl:
dev: "https://some-dev-url/"
stage: "https://a-staging-url/"
prod: "https://production-url"
的Makefile:
BASEDIR =$(CURDIR)
CONFDIR =$(BASEDIR)
OUTPUTDIR =$/../build
DEVDIR =$(OUTPUTDIR)/dev
PRODDIR =$(OUTPUTDIR)/prod
STAGEDIR =$(OUTPUTDIR)/stage
DEVCONF =$(CONFDIR)/config.dev.yml
PRODCONF =$(CONFDIR)/config.prod.yml
STAGECONF =$(CONFDIR)/config.stage.yml
USRCONFIG =$/../usr/config.yml
dev:
. $(BASEDIR)/parse_yaml.sh # include parse_yaml function
$(info $(parse_yaml $(USRCONFIG) 'config_')) # read yaml file
$(parse-yaml DEVURL is $(config_baseurl_dev)) # Get the baseurl:dev KEY
@echo ${DEVURL} # Print the DEVURL from KEY
sleep 1
rm -rfv $(DEVDIR) # Delete the DEVDIR b4 build
sleep 1
$(BUILDER) --config=$(DEVCONF) -b=$(DEVURL) # Inset the baseurl:dev KEY
parse_yaml.sh:
#!/bin/sh
parse_yaml() {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 |
awk -F$fs '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
}
}'
}
答
-
您似乎认为make配方的连续行是作为一个单独的shell执行的。这不是它的工作方式:每行都在单独的shell调用中执行。所以,当你执行
. $(BASEDIR)/parse_yaml.sh
它对你的食谱的其他部分没有影响。如果要在单个shell调用的上下文中执行完整配方,请将所有内容都放在一行中,并使用
;
,&&
或||
链接命令。您可以使用续行(一个\
作为行结束前的最后一个字符)为更好的可读性:command1 && \ command2 ; \ command3 || \ command4
-
当食谱是由化妆扩大,各
$
被视为一个参考做变量或功能。因此,扩大$(parse-yaml DEVURL is $(config_baseurl_dev))
化妆时会试图执行不存在(它是一个shell功能,不是简单的修修补补功能)
$(parse-yaml...
化妆功能。这个陈述将因此完全被忽略。如果你想保护一些从扩大这些$
迹象,加倍他们:$$(parse-yaml DEVURL is $$(config_baseurl_dev))
后化妆扩张将被传递到外壳为:
$(parse-yaml DEVURL is $(config_baseurl_dev))
这可能是你要哪个更接近。
-
你的一些变量定义是怪异:
OUTPUTDIR =$/../build
您从领先
$/
期待什么?有一个名为$/
没有自动make变量,但要无论如何都将展开,并因为它是不确定的,其结果将是一样的:OUTPUTDIR =../build
即使是你想要的东西,这是一个有点怪,你不觉得吗?除非有很好的理由这么做,否则请与Makefiles的可靠维护人员友好相处,并避免它。
答
生成文件
all:
$(foreach var,$(shell . $(CURDIR)/parse_yaml.sh; parse_yaml config.yaml 'config_'),$(eval $(var)))
$(info config_baseurl__dev is $(config_baseurl__dev))
$(info config_baseurl__stage is $(config_baseurl__stage))
$(info config_baseurl__prod is $(config_baseurl__prod))
结果如下。
make
config_baseurl__dev is "https://some-dev-url/"
config_baseurl__stage is "https://a-staging-url/"
config_baseurl__prod is "https://production-url"