如何将Shell命令输出整行加入Makefile的define?为何内容丢失?
问题描述
在Makefile中定义了如下代码块:
define deploy_meta $(shell git log -n 2 --oneline | awk '{print "commit"NR ": " $0}') commit: nogit-$(timestamp) tag: nogit-$(timestamp) deployed-from: $(shell hostname) deployed-by: $(USER) deploy-date: $(shell date -u '+%Y%m%d%H%M%S') endef
生成的.deploy文件内容异常:
$cat .deploy commit1: commit2: commit: nogit-1669806282 tag: nogit-1669806282 ...
单独执行命令git log -n 2 --oneline | awk '{print "commit"NR ": " $0}'能正常输出两行完整提交信息,但在Makefile的define中使用时丢失提交内容,且两行合并为一行。
原因分析
- $符号解析优先级冲突:Makefile中
$是特殊字符,用于引用变量。awk命令里的$0会被Makefile优先解析,而非传递给awk执行,导致awk无法获取git log输出的行内容,最终输出空值。 - $(shell)函数的换行处理逻辑:
$(shell)默认会将命令输出中的所有换行符替换为空格,因此git log输出的两行内容被合并成一行,出现commit1: commit2:的结果。
解决方案
针对两个问题分别处理:
- 转义$符号:将awk命令中的
$改为$$,让Makefile将$0原样传递给awk。 - 保留换行格式:可以通过两种方式实现:
- 方式一:拆分git log命令,分别获取两次提交记录,避免
$(shell)合并换行:define deploy_meta commit1: $(shell git log -n 1 --oneline) commit2: $(shell git log -n 1 --skip=1 --oneline) commit: nogit-$(timestamp) tag: nogit-$(timestamp) deployed-from: $(shell hostname) deployed-by: $(USER) deploy-date: $(shell date -u '+%Y%m%d%H%M%S') endef - 方式二:在shell命令中为输出添加换行转义,生成文件时用
echo -e解析转义字符:define deploy_meta $(shell git log -n 2 --oneline | awk '{print "commit"NR ": " $$0}' | sed 's/$$/\\n/') commit: nogit-$(timestamp) tag: nogit-$(timestamp) deployed-from: $(shell hostname) deployed-by: $(USER) deploy-date: $(shell date -u '+%Y%m%d%H%M%S') endef .deploy: echo -e "$(deploy_meta)" > $@
- 方式一:拆分git log命令,分别获取两次提交记录,避免
内容的提问来源于stack exchange,提问作者Dims
相关产品推荐
相关产品推荐

