Python含数字驼峰转大写蛇形的正则表达式问题排查
驼峰转大写蛇形命名的正则问题分析
问题场景
编写了Python方法通过正则将驼峰式字符串转为大写蛇形命名(screaming snake case),要求在大小写变化处、非数字与数字字符之间插入下划线,但测试出现不符合预期的结果:
- 输入
vn3b返回VN3B,预期为VN_3_B - 输入
vnRbb250V返回VN_RBB_250V,预期为VN_RBB_250_V
原实现代码:
import re def camel_to_screaming_snake(value): return '_'.join(re.findall('[A-Z][a-z]+|[0-9A-Z]+(?=[A-Z][a-z])|[0-9A-Z]{2,}|[a-z0-9]{2,}|[a-zA-Z0-9]' , value)).upper()
正则表达式的核心问题
当前正则的分支匹配逻辑存在三个关键缺陷:
- 分支优先级导致范围过度匹配:正则分支按顺序匹配,
[a-z0-9]{2,}会把连续的小写字母+数字(比如vn3)整体匹配,不会拆分为vn和3;同理[0-9A-Z]{2,}会把250V整体匹配,使得数字和后面的大写字母无法拆分。 - 未明确区分数字与字母的边界:原正则没有单独处理数字与字母相邻的场景,无法在两者之间插入下划线。
- 末尾单个大写字母的匹配遗漏:字符串末尾的单个大写字母(比如
vnRbb250V中的V)会被前面的[0-9A-Z]{2,}分支包含,导致无法单独拆分出来。
修正方案
方案一:分步插入下划线(逻辑更清晰)
换一种思路,先在需要拆分的位置插入下划线,再统一转大写:
import re def camel_to_screaming_snake(value): # 小写转大写的位置前插入下划线 temp = re.sub(r'([a-z])([A-Z])', r'\1_\2', value) # 非数字与数字相邻处插入下划线 temp = re.sub(r'([^\d])(\d)', r'\1_\2', temp) # 数字与非数字相邻处插入下划线 temp = re.sub(r'(\d)([^\d])', r'\1_\2', temp) # 转为大写 return temp.upper()
测试验证:
- 输入
vn3b→ 输出VN_3_B - 输入
vnRbb250V→ 输出VN_RBB_250_V
方案二:调整正则分支(基于findall实现)
重新设计正则分支,确保每个需要拆分的单元被单独匹配:
import re def camel_to_screaming_snake(value): return '_'.join(re.findall( r'[A-Z][a-z]+|\d+|[A-Z]|[a-z]+', value )).upper()
分支逻辑说明:
[A-Z][a-z]+:匹配大写开头后跟连续小写的组合(如Rbb)\d+:匹配连续数字(如250)[A-Z]:匹配单个大写字母(如V)[a-z]+:匹配连续小写字母(如vn)
内容的提问来源于stack exchange,提问作者work89
相关产品推荐
相关产品推荐

