You need to enable JavaScript to run this app. GNU Make 4.2.1 如何从空格分隔字符串构建数组?
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make 4.2.1 如何从空格分隔字符串构建数组?

GNU Make 4.2.1 遍历空格分隔目标列表的实现方案

之前bash方案不生效的原因

找的bash实现方案跑不通,本质是两个常见的认知误区:

  • GNU Make 执行 recipe 时,默认调用系统符合 POSIX 规范的 shell(Debian/Ubuntu 下默认是 dash),不会主动启用 bash 的专属语法,依赖 bash 数组的写法会直接抛语法错误
  • 没必要执着于把字符串转成“数组”才能遍历——不管是 Make 本身的内置函数,还是 POSIX 标准的 shell,对空白分隔的字符串,天生就支持按单词拆分遍历

方案一:直接在 Make 层面完成遍历(推荐)

你已经拿到的TARGETS本身就是 Make 存储的空白分隔字符串,对于 Make 的内置文本函数来说,这类字符串天生就是可遍历的单词列表,完全不需要转成 shell 侧的数组。
结合你要实现的“检查模式匹配值$*是否为其他目标前缀”的需求,直接用foreach函数就能完成遍历逻辑,示例代码:

# 顶层定义目标列表,比在 recipe 里用 eval 执行 shell 命令效率更高
TARGETS := $(sort $(shell grep -Ph "^[^\t].*::.*##" ./Makefile | cut -d : -f 1))

%::
	@echo "当前匹配的模式值: $*"
	# 直接遍历 TARGETS 中的每个单词,完成前缀判断
	$(foreach tgt,$(TARGETS),\
		$(if $(filter $(strip $tgt),$(strip $*)%),\
			@echo "发现关联目标: $tgt",\
		)\
	)

这种写法的优势:

  • 所有遍历、判断逻辑都在 Make 解析阶段完成,不需要调用额外的 shell 逻辑,执行速度更快
  • 完全兼容 GNU Make 4.2.1 的版本特性,不存在不同 shell 环境差异导致的兼容问题
  • 不需要处理 shell 转义的问题,避免目标名带特殊字符时触发的命令执行错误

方案二:在 recipe 的 shell 逻辑中实现兼容遍历

如果后续需要在 shell 环境下完成更复杂的处理逻辑,不需要依赖 bash 数组,用 POSIX 全兼容的位置参数拆分法,就能实现和数组完全等价的遍历效果,示例代码:

%::
	@set -- $(TARGETS); \
	for tgt in "$@"; do \
		# 用 shell 字符串截断判断前缀关系
		if [ -n "${tgt##$*}" ] && [ "${tgt##$*}" != "$tgt" ]; then \
			echo "目标 $tgt 与匹配值 $* 存在前缀关联"; \
		fi; \
	done

这里的实现逻辑:

  • set -- $(TARGETS) 会把空白分隔的TARGETS字符串,按单词拆分成 shell 的位置参数,存储效果和 bash 数组完全一致
  • 后续通过"$@"引用所有拆分后的单个单词,在循环中逐个处理
  • 这种写法不需要 bash 环境,不管是 dash、bash、ksh 都能正常执行,从根本上解决了之前 bash 方案不生效的问题

常见避坑点

  • 不要在 recipe 中直接使用 bash 专属的数组语法(比如arr=($VAR)、${arr[@]}),除非你显式指定用 bash 执行命令,否则会直接触发语法错误
  • 拆分单词时不要给$(TARGETS)加全引号,否则整个字符串会被当成单个元素,无法完成逐个遍历
  • 前缀判断不要直接做全字符串比对,要使用 Make 的filter函数或者 shell 的字符串截断逻辑,避免短字符的误匹配

内容的提问来源于stack exchange,提问作者artu-hnrq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 17:36:05