You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Makefile脚本中对环境变量执行字符串替换?

在Makefile中处理字符串替换的正确方法

问题场景

你有如下Makefile脚本:

build:
    DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR=${GITHUB_ACTOR} --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} -t ${DOCKER_REGISTRY}/strick:${IMAGE_BRANCH}-${IMAGE_TAG} -t ${DOCKER_REGISTRY}/strick:${IMAGE_BRANCH}-latest .

当${IMAGE_BRANCH}包含斜杠(如feature/a-b-c)时,Docker构建会失败——因为镜像标签不允许包含斜杠。你尝试通过shell命令替换斜杠为横杠,但写法有误,导致CLEANED_IMAGE_BRANCH为空,执行时报错:

❮❮❮ DOCKER_REGISTRY=docker IMAGE_BRANCH="a/b" IMAGE_TAG="lol" make build
CLEANED_IMAGE_BRANCH=
DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR= --build-arg GITHUB_TOKEN= -t docker/strick:-lol -t docker/strick:-latest .
invalid argument "docker/strick:-lol" for "-t, --tag" flag: invalid reference format
See 'docker build --help'.
make: *** [build] Error 125

解决方法

方法一:使用Makefile原生字符串替换(推荐)

Makefile内置了变量替换语法,无需调用shell,效率更高且避免子shell问题。语法为$(变量:原字符=替换字符):

写法1:直接在命令中替换

build:
	DOCKER_BUILDKIT=1 docker build \
		--build-arg GITHUB_ACTOR=${GITHUB_ACTOR} \
		--build-arg GITHUB_TOKEN=${GITHUB_TOKEN} \
		-t ${DOCKER_REGISTRY}/strick:$(IMAGE_BRANCH:/=-)-${IMAGE_TAG} \
		-t ${DOCKER_REGISTRY}/strick:$(IMAGE_BRANCH:/=-)-latest .

写法2:提前定义清理后的变量

# 立即展开变量,解析Makefile时完成替换
CLEANED_IMAGE_BRANCH := $(IMAGE_BRANCH:/=-)

build:
	DOCKER_BUILDKIT=1 docker build \
		--build-arg GITHUB_ACTOR=${GITHUB_ACTOR} \
		--build-arg GITHUB_TOKEN=${GITHUB_TOKEN} \
		-t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-${IMAGE_TAG} \
		-t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-latest .

方法二:通过Shell命令处理(需保证同进程执行)

如果必须用shell命令(比如复杂替换逻辑),要注意Makefile中每行缩进的命令都是单独的shell进程,变量无法跨进程共享。需要把变量定义和构建命令放在同一个进程中,用; \连接多行:

build:
	CLEANED_IMAGE_BRANCH=$$(echo ${IMAGE_BRANCH} | sed 's/\//-/g'); \
	DOCKER_BUILDKIT=1 docker build \
		--build-arg GITHUB_ACTOR=${GITHUB_ACTOR} \
		--build-arg GITHUB_TOKEN=${GITHUB_TOKEN} \
		-t ${DOCKER_REGISTRY}/strick:$${CLEANED_IMAGE_BRANCH}-${IMAGE_TAG} \
		-t ${DOCKER_REGISTRY}/strick:$${CLEANED_IMAGE_BRANCH}-latest .

注意要点:

  • 用$$转义成shell的$,避免被Makefile解析为自身变量
  • 用; \连接所有命令,确保它们在同一个shell进程中执行,这样CLEANED_IMAGE_BRANCH才能被后续命令读取

验证效果

执行测试命令:

DOCKER_REGISTRY=docker IMAGE_BRANCH="a/b" IMAGE_TAG="lol" make build

会生成合法的镜像标签:docker/strick:a-b-lol和docker/strick:a-b-latest,构建可以正常执行。

内容的提问来源于stack exchange,提问作者Paymahn Moghadasian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:45:36