shell 是否可以在make目标的if语句中将一个变量与多个值进行比较?

l7mqbcuq  于 2023-04-21  发布在  Shell
关注(0)|答案(4)|浏览(148)

我正在尝试运行一个make目标,其中一个特定的值在CLI上传递,但这个值应该与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块应该被执行!

jgzswidk

jgzswidk1#

过滤器GNU make函数是你的好朋友:

.PHONY:plan-infra

MATCH := $(filter emr gmr,$(infra_module_path))

plan-infra: configure  ## Plan Infra
    @if [ -n "$(MATCH)" ]; then\
        echo "test";\
    fi

但请注意,如果传递的值包含多个空格分隔的标记,并且至少有一个匹配,则也会匹配,例如,

make plan-infra -e infra_module_path="emr foo bar"

正如MadScientist所指出的,filter-out稍微好一点,因为当字符串只包含过滤后的标记时,它返回空字符串;因此它更准确:

.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
rryofs0p

rryofs0p2#

可以使用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
mf98qq94

mf98qq943#

我可能会建议使用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

(注意,ifeqelseendif前面有空格,而不是制表符--您实际上并不需要空格,但它们对可读性很有用)

fbcarpbf

fbcarpbf4#

我认为,这个问题可以通过这些方法彻底解决:
1.使用filter,而不是findsting-选择精确匹配。
1.使用words,过滤掉(先验不正确的)多词参数。
1.也许split,如果空格允许的话(不是我的情况)。
这种方法允许与两个或可能更多的参数值进行比较。
这是我的项目中的插图,但经过适当的重命名:

ifeq ($(words ${infra_module_path}),1)
  MATCH:=$(or $(filter emr,${infra_module_path}),$(filter gmr,${infra_module_path}),$(filter qa,${infra_module_path}),$(filter pre-prod,${infra_module_path}))
else
  MATCH:=
endif
$(if ${MATCH},,$(error not recognised infra_module_path))

相关问题