在Make规则中分割字符串

use*_*016 0 makefile gnu-make

我试图在Make target中用冒号分隔的值分割字符串。

当我尝试使用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
Run Code Online (Sandbox Code Playgroud)

输出是

new
new
Run Code Online (Sandbox Code Playgroud)

而所需的输出是

new e7e45d89-94cc-4783-86c5-2236d9904a24 new 
test 2af1d689-98c3-48f2-984d-2ea21c5135dd new
Run Code Online (Sandbox Code Playgroud)

Mad*_*ist 5

这似乎是关于makefile的最常见的混淆:用shell语法编写的配方与make结构之间的区别。

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

在您的示例中,您试图使一个包含make变量和函数的shell脚本循环:无法正常工作(shell如何进行工作,shell是make的一个新过程,请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
Run Code Online (Sandbox Code Playgroud)

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

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

然后扩展下一行:

    $(eval f=$(shell echo $i | cut -d: -f 1))  \
Run Code Online (Sandbox Code Playgroud)

$i只是一个make变量i,您从未设置过,因此为空。因此,make运行以下shell命令:

echo | cut -d: -f 1
Run Code Online (Sandbox Code Playgroud)

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

同样这行:

    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
Run Code Online (Sandbox Code Playgroud)

设置fid为空字符串。

然后这行扩展

    echo $(f) $(fid) $(f1) ;\
Run Code Online (Sandbox Code Playgroud)

扩展为:

    echo   new ;\
Run Code Online (Sandbox Code Playgroud)

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

done
Run Code Online (Sandbox Code Playgroud)

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

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

在配方$(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
Run Code Online (Sandbox Code Playgroud)