是否可以在 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 DuffyMadScientist 所指出的,最好使用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 elseendif 前面有空格而不是制表符——您实际上不需要这些空格,但它们有助于提高可读性)