获取GNU Makefile目标异常:another-command未被识别的原因?
问题分析与解决方案
一、原awk命令无法识别带连字符目标的原因
你的原awk命令看似允许-,但实际可能因正则细节漏匹配:
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\\\/t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
这里的正则^[a-zA-Z0-9][^$#\\\/t=]*:中,[^$#\\\/t=]是排除$#\/t=这些字符,理论上-是被允许的,但可能因为以下原因漏匹配:
- shell转义问题:如果你的shell(比如bash)对反斜杠的转义处理,导致awk实际收到的正则排除了额外字符;
- awk版本差异:某些旧版本awk对正则中特殊字符的解析存在偏差;
make -qp输出格式:少数情况下,带连字符的目标可能被make以不同格式输出(比如附带隐式规则标记),导致正则不匹配。
二、你尝试的grep命令报错的原因
你用的grep命令:
make -qp | grep '^[a-z0-9-]\+:'
报错核心是正则表达式中非法的字符范围:
在grep默认的基本正则表达式(BRE)模式下,[]中的-如果放在两个字符中间,会被解析为字符范围(比如0-9表示0到9的数字)。而你写的[a-z0-9-]中,0-9-会被尝试解析为从0到-的范围,但-的ASCII码(45)比0(48)小,属于反向范围,grep会判定为无效,抛出类似invalid range end的错误。
三、正确的解决方案
方案1:修正awk命令,明确允许连字符
调整正则,直接把-加入允许的字符集,避免歧义:
make -qp | awk -F':' '/^[a-zA-Z0-9-][a-zA-Z0-9-]*:([^=]|$)/ {print $1}'
或者用更简洁的扩展正则写法(需awk支持ERE,加-E参数):
make -qp | awk -F':' -E '/^[a-zA-Z0-9-]+:([^=]|$)/ {print $1}'
这个命令直接打印冒号前的目标名,无需split(因为-F':'后$1就是纯目标名,没有空格)。
方案2:修正grep命令,避免非法范围
有两种方式解决grep的正则问题:
- 把
-放到字符集的开头或结尾:这样grep会把它当成普通字符,而非范围分隔符:make -qp | grep '^[-a-z0-9]\+:' - 使用扩展正则表达式(ERE)模式:加
-E参数,同时用+更清晰:make -qp | grep -E '^[-a-z0-9]+:'
方案3:更可靠的通用写法
如果要兼容更多特殊字符(比如下划线),可以用更宽松的正则匹配Makefile目标:
make -qp | awk '/^[a-zA-Z0-9_-]+:/ && !/^\./ && !/^=/ {print substr($0, 1, index($0, ":")-1)}'
这个命令:
- 匹配开头是字母、数字、下划线、连字符的目标;
- 排除以
.开头的隐含目标(比如.PHONY)和以=开头的变量; - 通过
substr精准截取冒号前的目标名。
内容的提问来源于stack exchange,提问作者NSS
相关产品推荐
相关产品推荐

