如何用Python regex匹配非关键字、非注释、非引号内的合法变量名?
变量名匹配解决方案:排除关键字、注释行与双引号包裹内容
最终实现正则
import regex var_pattern = regex.compile( r'(?:"[^"]*"|;.*$(*SKIP)(*FAIL))|(?!\b(?:OR|AND|IF|THEN|ELSE|READ_GENERIC_TABLE)\b)\b([A-Z][A-Z0-9_]{0,35})\b', flags=regex.MULTILINE )
逻辑说明
这个正则采用优先跳过无效内容的策略,利用mrab-regex支持的(*SKIP)(*FAIL)原子操作实现精准过滤:
- 跳过双引号包裹内容:
"[^"]*"匹配完整的双引号字符串,直接跳过不参与后续匹配 - 跳过注释行内容:
;.*$(*SKIP)(*FAIL)匹配分号开头的整行注释,(*SKIP)(*FAIL)标记这部分内容完全排除在匹配结果外 - 匹配合法变量:
- 负前瞻
(?!\b(?:OR|AND|IF|THEN|ELSE|READ_GENERIC_TABLE)\b)排除指定关键字 \b([A-Z][A-Z0-9_]{0,35})\b严格匹配符合规则的变量名(大写字母起始,后续可跟0-35个大写字母、数字或下划线)
- 负前瞻
测试验证
针对给定测试字符串执行匹配:
test_string = """ IF t = 0 OR t > POL_TERM_M THEN 0 ELSE IF mult(t+11,12) AND POLICY_YEAR <= TBL_VAL_INT_Y THEN READ_GENERIC_TABLE(TBL_VAL_INT, "Y", ENTRY_YEAR, MVA_OPT, "VAR_NAME", POLICY_YEAR(t)) ELSE VALINT_EL_PC(t-1) """ valid_vars = [var for var in var_pattern.findall(test_string) if var] print(valid_vars)
输出结果完全符合预期:['POL_TERM_M', 'POLICY_YEAR', 'TBL_VAL_INT_Y', 'TBL_VAL_INT', 'ENTRY_YEAR', 'MVA_OPT', 'VALINT_EL_PC']
之前尝试的问题分析
此前添加的[^"]存在两个核心问题:
- 破坏了单词边界
\b的判断逻辑,导致变量前后的非引号字符(如空格、括号)被纳入匹配判断,进而误捕关键字 - 无法覆盖变量位于行首/行尾等无前后非引号字符的场景,匹配范围受限
而(*SKIP)(*FAIL)的方式直接将无效内容从匹配池中移除,剩余内容仅需处理合法变量的匹配,逻辑更简洁可靠。
内容的提问来源于stack exchange,提问作者SecBen.dev
相关产品推荐
相关产品推荐

