Bash in Make:如何扩展动态变量名?

时间:2015-09-15 02:48:26

标签: bash makefile gnu-make

为了说明这个问题,我创建了一个makefile,它先定义一个汽车列表,然后为每辆汽车创建一个颜色列表:

CARS = Ford Ferrari Mercedes Toyota
Ford_COLOURS = black blue red white
Ferrari_COLOURS = red
Mercedes_COLOURS = black blue silver
Toyota_COLOURS = blue red white

然后,我想在我的一个制作目标中遍历每辆车的所有颜色:

.PHONY: list
list:
    for car in ${CARS} ; do \
        car_colours=$${car}_COLOURS ; \
        echo $${car_colours} = "$${!car_colours}" ; \
        eval colours="$${!car_colours}" ; \
        for colour in $${colours} ; do \
            echo $${colour} ; \
        done ; \
    done

正如您所看到的,我尝试综合this question about generating dynamic variable names in bash中的想法和this question about how to evaluate (expand) dynamic names in bash的一些答案。

不幸的是我得到以下输出:

Ford_COLOURS = 
Ferrari_COLOURS = 
Mercedes_COLOURS = 
Toyota_COLOURS =

虽然我希望得到这样的东西:

Ford_COLOURS = black blue red white
black 
blue 
red 
white
Ferrari_COLOURS = red
red
Mercedes_COLOURS = black blue silver
black 
blue 
silver
Toyota_COLOURS = blue red white
blue 
red 
white

我该如何解决?

2 个答案:

答案 0 :(得分:2)

my commentJonathan's answer之后,我找到了一种方法,涉及从执行内部make循环的片段中启动另一个for进程:

.PHONY: list
list:
    for car in ${CARS} ; do \
        car_colours_var=$${car}_COLOURS ; \
        ${MAKE} CAR_COLOURS_VAR=$${car_colours_var} single_car ; \
    done

.PHONY: single_car
single_car:
    for colour in ${${CAR_COLOURS_VAR}} ; do \
        echo $${colour} ; \
    done

密钥是中间CAR_COLOURS_VAR,它作为参数传递给子make进程,随后可以通过${${CAR_COLOURS_VAR}}语法扩展该进程。

答案 1 :(得分:1)

问题是shell不知道'make_COLOURS'的列表。您可以使用:

CARS = Ford Ferrari Mercedes Toyota
Ford_COLOURS = black blue red white
Ferrari_COLOURS = red
Mercedes_COLOURS = black blue silver
Toyota_COLOURS = blue red white

.PHONY: list
list:
        Ford_COLOURS="${Ford_COLOURS}"; \
        Ferrari_COLOURS="${Ferrari_COLOURS}"; \
        Mercedes_COLOURS="${Mercedes_COLOURS}"; \
        Toyota_COLOURS="${Toyota_COLOURS}"; \
        for car in ${CARS} ; do \
            car_colours=$${car}_COLOURS ; \
            echo $${car_colours} = "$${!car_colours}" ; \
            colours="$${!car_colours}" ; \
            for colour in $${colours} ; do \
                echo $${colour} ; \
            done ; \
        done

请注意,原始eval中的eval colours="$${!car_colours}"已丢失eval。如果存在,则会出现/bin/sh: blue: command not found之类的错误,因为evalcolours=black blue red white并尝试执行blue,并将环境变量colours设置为{{} 1}}。