如何在m4中定义大小写不敏感的宏名称?
解决方案
以下是两种可直接落地的优化方案,均无需手动编写所有大小写变体的宏定义:
方案1:正则匹配替换(最简单,适合固定替换场景)
直接使用m4内置的patsubst函数,构造不区分大小写的正则匹配目标词即可,不需要单独定义宏。
针对你提出的mov替换需求,写法如下:
dnl 匹配所有大小写组合的mov,统一替换为小写mov patsubst(`Mov MOV moV mOv', `[mM][oO][vV]', `mov')
运行后输出就是mov mov mov mov,完全符合要求。
如果需要替换更长的单词,比如4个字母的test,仅需把正则改成[tT][eE][sS][tT]即可,不需要写16个宏定义。如果需要全局处理所有输入内容,把上述逻辑封装成全局处理规则即可,不需要逐个调用。
方案2:自动生成所有大小写变体的宏定义(适合需要保留宏调用逻辑的场景)
如果你的场景必须用宏定义的方式实现(比如宏需要带参数、有额外处理逻辑),可以写一个通用生成宏,自动递归生成目标词所有大小写组合的宏定义,无需手动编写:
dnl 通用宏:为第一个参数的所有大小写变体定义宏,展开值为第二个参数 define(`def_case_insensitive_macro', ` _gen_all_case_defs(`$1', `$2', len(`$1'), 0) ') dnl 内部递归逻辑,自动生成所有大小写组合的define语句 define(`_gen_all_case_defs', ` ifelse($3, $4, `define(`$1', `$2')', `_gen_all_case_defs(translit($1, substr($1, $4, 1), tolower(substr($1, $4, 1))), $2, $3, incr($4)) _gen_all_case_defs(translit($1, substr($1, $4, 1), toupper(substr($1, $4, 1))), $2, $3, incr($4)) ') ') dnl 使用示例:仅需一行即可完成mov所有大小写变体的宏定义 def_case_insensitive_macro(`mov', `mov')
调用后不管是Mov、MOV还是其他大小写组合,都会自动展开为mov,即使是5个字母的单词,也只需要调用一次即可,不需要手动写32个define。
注意事项
- 正则匹配方案仅适合固定文本替换场景,如果你的宏需要带参数,建议使用第二种自动生成宏的方案。
- 上述代码兼容GNU m4,也就是绝大多数Linux发行版默认携带的m4版本。
内容的提问来源于stack exchange,提问作者siv2r
相关产品推荐
相关产品推荐

