是否可以在 make 目标的 if 语句中比较具有多个值的变量?
Is it possible to compare a variable with multiple values in if statement of a make target?
我正在尝试 运行 一个在 CLI 上传递特定值的 make 目标,但是这个值应该与 2 个或更多可能的值进行比较,比如在 cli 上传递的值应该等于现有列表中的任何一个,以便条件变为真,如果块被执行!
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@if [ "${infra_module_path}" = "emr" or "gmr" ]; then\
echo "test";\
fi
$ make plan-infra -e infra_module_path=emr
因此,如果变量“infra_module_path”是“emr”或“gmr”,则应该执行 if 块!
filter GNU make function是你的朋友:
.PHONY:plan-infra
MATCH := $(filter emr gmr,$(infra_module_path))
plan-infra: configure ## Plan Infra
@if [ -n "$(MATCH)" ]; then\
echo "test";\
fi
但请注意,如果您传递的值包含多个 space 分隔的标记且至少有一个匹配,这也会匹配,例如,
make plan-infra -e infra_module_path="emr foo bar"
正如 MadScientist 所指出的,filter-out
更好一些,因为它 returns 当字符串仅包含过滤后的标记时它是空字符串;因此更准确:
.PHONY:plan-infra
MATCH := $(filter-out emr gmr,$(infra_module_path))
plan-infra: configure ## Plan Infra
@if [ -z "$(MATCH)" ]; then\
echo "test";\
fi
但仍然不是 100% 准确:
make plan-infra -e infra_module_path="emr qmr"
仍然匹配。如果你真的需要精确匹配,虽然它可以用 make 函数实现(至少在你的情况下),正如 Charles Duffy 和 MadScientist 所指出的,最好使用shell 构造。以防万一您绝对需要使用 make 函数进行精确匹配:
.PHONY:plan-infra
ifeq ($(words $(infra_module_path)),1)
MATCH := $(filter-out emr gmr,$(infra_module_path))
else
MATCH := no
endif
plan-infra: configure ## Plan Infra
@if [ -z "$(MATCH)" ]; then\
echo "test";\
fi
您可以使用 shell OR (-o) 条件,或使用 case
语句来检查两个可能值之一。 case 语句更容易理解一些。
使用如果:
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@if [ "${infra_module_path}" = "emr" -o "${infra_module_path}" = "gmr" ]; then\
echo "test";\
fi
$ make plan-infra -e infra_module_path=emr
使用案例:
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@case "${infra_module_path"}" in emr | gmr) echo "test";; esac
$ make plan-infra -e infra_module_path=emr
我可能建议使用 make 条件而不是 bash。你可能想做:
plan-infra: configure ## Plan Infr
ifeq ($(filter-out emr gmr,$(infra_module_path)),)
@echo "in emr or gmr";
else
@echo "not in emr or gmr"
endif
(注意 ifeq
else
和 endif
前面有空格而不是制表符——您实际上不需要这些空格,但它们有助于提高可读性)
我正在尝试 运行 一个在 CLI 上传递特定值的 make 目标,但是这个值应该与 2 个或更多可能的值进行比较,比如在 cli 上传递的值应该等于现有列表中的任何一个,以便条件变为真,如果块被执行!
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@if [ "${infra_module_path}" = "emr" or "gmr" ]; then\
echo "test";\
fi
$ make plan-infra -e infra_module_path=emr
因此,如果变量“infra_module_path”是“emr”或“gmr”,则应该执行 if 块!
filter GNU make function是你的朋友:
.PHONY:plan-infra
MATCH := $(filter emr gmr,$(infra_module_path))
plan-infra: configure ## Plan Infra
@if [ -n "$(MATCH)" ]; then\
echo "test";\
fi
但请注意,如果您传递的值包含多个 space 分隔的标记且至少有一个匹配,这也会匹配,例如,
make plan-infra -e infra_module_path="emr foo bar"
正如 MadScientist 所指出的,filter-out
更好一些,因为它 returns 当字符串仅包含过滤后的标记时它是空字符串;因此更准确:
.PHONY:plan-infra
MATCH := $(filter-out emr gmr,$(infra_module_path))
plan-infra: configure ## Plan Infra
@if [ -z "$(MATCH)" ]; then\
echo "test";\
fi
但仍然不是 100% 准确:
make plan-infra -e infra_module_path="emr qmr"
仍然匹配。如果你真的需要精确匹配,虽然它可以用 make 函数实现(至少在你的情况下),正如 Charles Duffy 和 MadScientist 所指出的,最好使用shell 构造。以防万一您绝对需要使用 make 函数进行精确匹配:
.PHONY:plan-infra
ifeq ($(words $(infra_module_path)),1)
MATCH := $(filter-out emr gmr,$(infra_module_path))
else
MATCH := no
endif
plan-infra: configure ## Plan Infra
@if [ -z "$(MATCH)" ]; then\
echo "test";\
fi
您可以使用 shell OR (-o) 条件,或使用 case
语句来检查两个可能值之一。 case 语句更容易理解一些。
使用如果:
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@if [ "${infra_module_path}" = "emr" -o "${infra_module_path}" = "gmr" ]; then\
echo "test";\
fi
$ make plan-infra -e infra_module_path=emr
使用案例:
.PHONY:plan-infra
plan-infra: configure ## Plan Infra
@case "${infra_module_path"}" in emr | gmr) echo "test";; esac
$ make plan-infra -e infra_module_path=emr
我可能建议使用 make 条件而不是 bash。你可能想做:
plan-infra: configure ## Plan Infr
ifeq ($(filter-out emr gmr,$(infra_module_path)),)
@echo "in emr or gmr";
else
@echo "not in emr or gmr"
endif
(注意 ifeq
else
和 endif
前面有空格而不是制表符——您实际上不需要这些空格,但它们有助于提高可读性)