如何让M4中先定义的宏调用后续定义的宏并生效?
m4宏定义无法正常展开的问题解决办法
问题场景
我有一个包含宏定义的文件tools.m4,内容如下:
define([YEAR_2_DIGITS], substr(YEAR, [2], [2]))
在另一个文件query.sql中调用该宏,内容如下:
changequote(`[', `]') include(./tools.m4) define([YEAR], [2017]) YEAR_2_DIGITS
执行命令m4 query.sql后,返回结果为:
AR
而非预期的17。
原因分析
问题源于m4的宏展开机制:定义YEAR_2_DIGITS时,第二个参数substr(YEAR, [2], [2])未被引号包裹,m4会立即展开该表达式。此时YEAR尚未定义,会被当作字符串"YEAR"处理,substr("YEAR", 2, 2)的计算结果为"AR",因此YEAR_2_DIGITS被直接定义为"AR",后续即使定义了YEAR也无法改变这一结果。
解决方法
修改tools.m4中的宏定义,将第二个参数用引号包裹,让m4延迟展开内部的YEAR变量,直到调用YEAR_2_DIGITS时再执行计算:
define([YEAR_2_DIGITS], [substr(YEAR, [2], [2])])
修改后重新执行m4 query.sql,即可得到预期的17。
此外,也可以调整query.sql中的代码顺序,先定义YEAR再引入tools.m4,但这种方式灵活性较差,优先推荐第一种方法。
内容的提问来源于stack exchange,提问作者pietrodito
相关产品推荐
相关产品推荐

