在Make规则中拆分字符串

时间:2017-07-03 19:57:55

标签: makefile gnu-make

我正在尝试在Make目标中拆分带冒号分隔值的字符串。

当我尝试使用for循环,eval,shell在目标配方中拆分字符串时,我得到空白值。当我使用shell命令将字符串拆分到目标结果之外的时候是肯定的。

任何人都可以帮我修复目标食谱。

以下是摘录。

notebooks=new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd
j=new:e7e45d89-94cc-4783-86c5-2236d9904a24
f1=$(shell echo $j | cut -d: -f 1)
test1:
    @for i in $(notebooks); \
    do \
        $(eval f=$(shell echo $i | cut -d: -f 1))  \
        $(eval fid=$(shell echo $i | cut -d: -f 2)) \
        echo $(f) $(fid) $(f1) ;\
    done

输出

new
new

而期望的输出是

new e7e45d89-94cc-4783-86c5-2236d9904a24 new 
test 2af1d689-98c3-48f2-984d-2ea21c5135dd new

1 个答案:

答案 0 :(得分:3)

这是关于makefile的最常见的混淆:用shell语法编写的 recipe 与make构造之间的区别。

make的工作方式是首先通过make评估配方中的 ALL make构造(变量和函数),然后将生成的扩展字符串传递给shell,shell执行它。 / p>

在您的示例中,您尝试使用包含make变量和函数的shell脚本循环:这不起作用(shell如何进行分叉,请求make重新扩展一些基于shell变量的值?)

当make想要运行这个食谱时:

@for i in $(notebooks); \
do \
    $(eval f=$(shell echo $i | cut -d: -f 1))  \
    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
    echo $(f) $(fid) $(f1) ;\
done

它首先展开所有makefile变量和函数。记住它只是在这里扩展一个字符串,它没有运行shell,所以没有调用shell命令。前两行扩展如下:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \

然后展开下一行:

    $(eval f=$(shell echo $i | cut -d: -f 1))  \

此处$i只是一个make变量i,您从未设置过它,因此它是空的。所以make运行这个shell命令:

echo | cut -d: -f 1

没有产生任何结果,因此展开$(eval f=)并将make变量f设置为空字符串。

同样这一行:

    $(eval fid=$(shell echo $i | cut -d: -f 2)) \

fid设置为空字符串。

然后这条线被扩展

    echo $(f) $(fid) $(f1) ;\

扩展为:

    echo   new ;\

因为这里只有f1有任何值。最后一行:

done

因此,在所有扩展之后,传递给要运行的shell的字符串是:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
    echo   new; \
done

在配方中使用$(shell ...) 绝对没有意义;你已经在shell中了,为什么还需要另外一个?同样,您不需要eval来设置make变量,您需要使用shell变量。

写下你的食谱:

@for i in $(notebooks); \
do \
    f=`echo $$i | cut -d: -f 1`;  \
    fid=`echo $$i | cut -d: -f 2`; \
    echo $$f $$fid $(f1) ;\
done