Shell makefile 中的循环语法 if/else
Shell loop syntax inside makefile if/else
我已经循环了,我需要将其添加到 if else
语句中,
如果值 ==app1
打印 x 否则打印 y
我试过以下方法
但是当我添加 else
时出现语法错误,
我做错了什么?
runners:
@for a in $(apps) ; do
if (( a == "app1"));then
echo first: $$v ;
else
echo second: $$v ;
fi
done
您对 sh
if/else 使用了错误的语法。并且您必须在命令的每一端添加一个 \
作为所有 运行 作为 make 启动的 shell 中的单个命令。注意:\
!
后没有空格
应该是这样的:
runners:
@for a in $(apps) ; do \
if [ $$a = "app1" ]; then\
echo first: $$a ; \
else \
echo second: $$a ; \
fi \
done
顺便说一句:你真的要打印$v
吗?我希望 $a
而不是 ;)
生成文件:
apps=app1 app2
runners:
@for a in $(apps) ; do \
if [ $$a = "app1" ]; then \
echo "first: $$a" ; \
else \
echo "second: $$a" ; \
fi \
done
打印
first: app1
second: app2
1) 我更喜欢用bash作为我的shell,因为我已经习惯了。因此,我在 makefile 的顶部使用 SHELL:=/bin/bash
。但是当系统不提供 /bin/bash..
时,您的整个 makefile 就会失败
2) 如果你想对食谱中的所有行使用相同的 shell,你可以使用特殊目标 .ONESHELL
这可以防止你在每个之后使用 ;\
后面没有空格的行(容易出错)。但是如果你使用 .ONESHELL
那么你的 makefile 中的所有食谱都是如此(我使用它,但你可能不想要)。
3) 如果 runners
不是文件(看起来像,因为您没有在食谱中创建文件),我建议将其设为 .PHONY
。当碰巧有一个名为 runners 的文件时,这会阻止 make 执行它。
4) 双括号((...))
用于算术展开。它根本无法比较字符串。使用单括号或双括号。参见 this great post。
5) 我还认为您想要打印 a
,因此将 $$v
替换为 $$a
。
所以总的来说,只要你有 /bin/bash:
SHELL:=/bin/bash
.ONESHELL:
.PHONY: runners
apps:=app2 app3 app1 app5
runners:
@for a in $(apps) ; do <<-- ; between commands as usual
if [[ "$$a" == "app1" ]]; then
echo first: $$a <<-- no need for ; because of .ONESHELL
else
echo second: $$a
fi
done
Output:
second: app2
second: app3
first: app1
second: app5
注意:上述解决方案仅适用于最近的 "make" 版本(可能 >4)。
OSX 例如包括 Gnu make 3.81。所以你需要使用 Homebrew
安装一个更新的 make
brew reinstall make --with-default-names
我已经循环了,我需要将其添加到 if else
语句中,
如果值 ==app1
打印 x 否则打印 y
我试过以下方法
但是当我添加 else
时出现语法错误,
我做错了什么?
runners:
@for a in $(apps) ; do
if (( a == "app1"));then
echo first: $$v ;
else
echo second: $$v ;
fi
done
您对 sh
if/else 使用了错误的语法。并且您必须在命令的每一端添加一个 \
作为所有 运行 作为 make 启动的 shell 中的单个命令。注意:\
!
应该是这样的:
runners:
@for a in $(apps) ; do \
if [ $$a = "app1" ]; then\
echo first: $$a ; \
else \
echo second: $$a ; \
fi \
done
顺便说一句:你真的要打印$v
吗?我希望 $a
而不是 ;)
生成文件:
apps=app1 app2
runners:
@for a in $(apps) ; do \
if [ $$a = "app1" ]; then \
echo "first: $$a" ; \
else \
echo "second: $$a" ; \
fi \
done
打印
first: app1
second: app2
1) 我更喜欢用bash作为我的shell,因为我已经习惯了。因此,我在 makefile 的顶部使用 SHELL:=/bin/bash
。但是当系统不提供 /bin/bash..
2) 如果你想对食谱中的所有行使用相同的 shell,你可以使用特殊目标 .ONESHELL
这可以防止你在每个之后使用 ;\
后面没有空格的行(容易出错)。但是如果你使用 .ONESHELL
那么你的 makefile 中的所有食谱都是如此(我使用它,但你可能不想要)。
3) 如果 runners
不是文件(看起来像,因为您没有在食谱中创建文件),我建议将其设为 .PHONY
。当碰巧有一个名为 runners 的文件时,这会阻止 make 执行它。
4) 双括号((...))
用于算术展开。它根本无法比较字符串。使用单括号或双括号。参见 this great post。
5) 我还认为您想要打印 a
,因此将 $$v
替换为 $$a
。
所以总的来说,只要你有 /bin/bash:
SHELL:=/bin/bash
.ONESHELL:
.PHONY: runners
apps:=app2 app3 app1 app5
runners:
@for a in $(apps) ; do <<-- ; between commands as usual
if [[ "$$a" == "app1" ]]; then
echo first: $$a <<-- no need for ; because of .ONESHELL
else
echo second: $$a
fi
done
Output:
second: app2 second: app3 first: app1 second: app5
注意:上述解决方案仅适用于最近的 "make" 版本(可能 >4)。 OSX 例如包括 Gnu make 3.81。所以你需要使用 Homebrew
安装一个更新的 makebrew reinstall make --with-default-names