如何在Makefile目标中正确使用Bash正则表达式?
这个问题我太熟了!Makefile的语法规则和Bash确实有不少冲突点,尤其是$符号的处理和默认shell环境的差异,我来给你拆解正确的写法:
首先得明确两个核心问题:
- Make默认用
/bin/sh执行命令,而[[ =~ ]]是Bash独有的正则匹配语法,所以必须强制用Bash来跑你的逻辑; - Make里的
$是变量引用的标记,所以所有要传给Bash的$都得转义成$$,不然会被Make提前解析成自己的变量。
下面是完整的可运行Makefile写法:
# 先指定用Bash执行所有recipe,避免sh不支持正则语法 SHELL := /bin/bash my-target: MY_STRING="FirstName-LastName-Gender-Age" ; \ MY_REGEX="([^-]+)-([^-]+)$$" ; \ if [[ $$MY_STRING =~ $$MY_REGEX ]]; then \ echo "完整匹配: $${BASH_REMATCH[0]}" ; \ echo "第一组(倒数第二个字段): $${BASH_REMATCH[1]}" ; \ echo "第二组(最后一个字段): $${BASH_REMATCH[2]}" ; \ fi
给你逐个解释关键细节:
SHELL := /bin/bash:这行一定要加,告诉Make放弃默认的sh,改用Bash执行后续命令,不然[[ =~ ]]会直接报错;MY_REGEX里的$写成$$:原本Bash正则里的$是行尾锚点,但Make会把单个$当成变量引用,所以必须转义成$$才能让Bash识别;$$MY_STRING、$$MY_REGEX:同理,Bash变量前的$必须转义,不然Make会试图去找名为MY_STRING的Make变量(而不是Bash变量);$${BASH_REMATCH[...]}:这里要写成两层转义,因为${BASH_REMATCH[0]}是Bash的数组引用,外层的$$让Make解析成单个$,最终传给Bash的就是正确的${BASH_REMATCH[0]};- 每行末尾的
\:Make的recipe里每行都是单独的shell进程,用\换行可以把所有命令放到同一个shell进程里,保证变量能跨命令使用。
如果你喜欢更紧凑的写法,也可以把逻辑打包成单个bash命令:
my-target: @bash -c 'MY_STRING="FirstName-LastName-Gender-Age"; MY_REGEX="([^-]+)-([^-]+)$"; if [[ $$MY_STRING =~ $$MY_REGEX ]]; then echo "匹配结果: $${BASH_REMATCH[0]}, 分组: $${BASH_REMATCH[1]}, $${BASH_REMATCH[2]}"; fi'
这种写法里同样要注意转义$,而且用@开头可以避免Make打印出完整的命令行,只输出你想要的结果。
内容的提问来源于stack exchange,提问作者code
相关产品推荐
相关产品推荐

