如何在Makefile中不依赖Shell实现列表对的键值查找?
两种Makefile键值映射查找方案
下面提供两种满足需求的实现:一种不依赖Shell,借助GMSL库实现纯Makefile逻辑;另一种是优化后的Shell实现,提升查找效率。
一、无Shell依赖:基于GMSL的实现
GMSL(GNU Make标准库)提供了键值对映射的原生支持,无需调用Shell即可完成查找:
# 引入GMSL库(确保gmsl.mk在Makefile可访问路径下) include gmsl.mk KEYS=key1 key2 key3 key4 key5 VALUES=val1 val2 val3 val4 val5 LOOKUPS=key2 key4 # 将KEYS和VALUES转换为GMSL键值映射 $(foreach idx,$(words $(KEYS)), \ $(eval $(call map-set,KEY_VAL_MAP,$(word $(idx),$(KEYS)),$(word $(idx),$(VALUES)))) \ ) # 遍历LOOKUPS,收集对应的值 RESULTS=$(foreach key,$(LOOKUPS),$(call map-get,KEY_VAL_MAP,$(key))) $(info RESULTS: $(RESULTS))
说明
- 通过
foreach遍历KEYS的索引,用map-set把每个键值对存入KEY_VAL_MAP映射 - 再用
foreach遍历LOOKUPS,通过map-get从映射中直接取出对应值,最终拼接成结果列表
二、优化后的Shell实现
原实现用嵌套循环时间复杂度为O(n*m),优化后借助Bash关联数组将查找复杂度降为O(n):
KEYS=key1 key2 key3 key4 key5 VALUES=val1 val2 val3 val4 val5 LOOKUPS=key2 key4 define CMD # 将KEYS和VALUES转为Bash关联数组 declare -A kv_map; \ keys=($(1)); \ vals=($(2)); \ for i in "$${!keys[@]}"; do \ kv_map["$${keys[$i]}"]="$${vals[$i]}"; \ done; \ # 遍历LOOKUPS直接取值 for key in $(3); do \ echo "$${kv_map[$key]}"; \ done endef RESULTS=$(shell bash -c '$(call CMD,$(KEYS),$(VALUES),$(LOOKUPS))') $(info RESULTS: $(RESULTS))
说明
- 先构建一次键值关联数组,避免重复遍历KEYS
- 遍历LOOKUPS时直接通过关联数组键名取值,大幅提升效率,尤其当KEYS/LOOKUPS元素较多时效果明显
内容的提问来源于stack exchange,提问作者amb
相关产品推荐
相关产品推荐

