Makefile遍历字符串列表转小写时变量为空的问题排查
Makefile遍历字符串转小写问题解决
问题根源
你写的代码存在几个关键错误:
- 变量解析顺序错误:Makefile会优先解析自身的变量和函数,再把处理后的命令交给shell执行。你用的
$($name)是Makefile的变量引用语法,意为“取名为name的变量的值”,但此时name是shell循环里的变量,Makefile解析阶段根本不存在这个变量,所以结果为空。 - $(eval)误用:
$(eval)是Makefile的内置函数,在Makefile解析阶段就会执行,而非shell循环运行时。此时shell的name变量还未赋值,自然无法得到正确结果。 - 换行符格式错误:recipe里每行末尾的
\后面不能有空格或多余换行,否则会导致shell命令语法出错。
解决方案
方法1:纯Shell循环处理(适合需要在shell中做复杂操作的场景)
直接用shell的变量和命令替换,注意用$$转义$,避免被Makefile提前解析:
# files in directory: test_file1.txt test_file2.txt test_file3.txt MYLIST = file1 file2 file3 recipe: for name in $(MYLIST) ; do \ FILENAME=$$(echo $$name | tr A-Z a-z) ; \ echo "Final name : test_$${FILENAME}.txt" ; \ done
$$name:让shell识别为循环变量name,而非Makefile变量$$(...):shell的命令替换语法,用来执行转小写的操作
方法2:提前用Makefile处理小写(更符合Makefile风格)
如果只是需要把列表转小写,可以先在Makefile阶段处理好,再循环输出:
MYLIST = file1 file2 file3 # 提前将列表转成小写(如果原列表包含大写字符串) LOWER_MYLIST = $(shell echo $(MYLIST) | tr A-Z a-z) recipe: $(foreach name,$(LOWER_MYLIST),echo "Final name : test_$(name).txt";)
用Makefile的foreach函数遍历列表,避免shell循环的解析问题,代码更简洁。
方法3:针对已有文件匹配(如果目标是处理目录中的txt文件)
如果你的目标是直接处理目录中的test_*.txt文件,还可以用Makefile的通配符自动匹配:
TXT_FILES = $(wildcard test_*.txt) recipe: for file in $(TXT_FILES) ; do \ echo "Final name : $$file" ; \ done
这种方式不需要手动维护MYLIST,自动匹配目录中的目标文件。
测试结果
运行修改后的Makefile,会输出预期内容:
Final name : test_file1.txt Final name : test_file2.txt Final name : test_file3.txt
内容的提问来源于stack exchange,提问作者KingFish
相关产品推荐
相关产品推荐

