如何在Vim替换中扩展反向引用处理多段驼峰式字符串?
Vim驼峰命名转大写下划线命名的正确处理方式
问题情况
我有一个三行内容的文件:
HelloStackOverflow ThisIsMyFirstPost OnThisWebsite
想要将其转换为:
HELLO_STACK_OVERFLOW THIS_IS_MY_FIRST_POST ON_THIS_WEBSITE
尝试使用以下Vim替换命令:
:%s/^\([A-Z][a-z]*\)*\([A-Z][a-z]*\)$/\U\1_\2/g
但由于重复捕获组\([A-Z][a-z]*\)*只会保留最后一次匹配的内容,导致输出结果错误:
STACK_OVERFLOW FIRST_POST THIS_WEBSITE
疑问:能否扩展反向引用让第一个捕获组的每次匹配后都添加下划线?
解决办法
不用纠结重复捕获组的反向引用限制,换个思路更高效:
两步替换(直观易调试)
- 先在小写字母与后续大写字母之间插入下划线:
:%s/\([a-z]\)\([A-Z]\)/\1_\2/g
执行后文本会变成:
Hello_Stack_Overflow This_Is_My_First_Post On_This_Website
- 再将所有内容统一转为大写:
:%s/.*/\U&/
即可得到目标格式。
一步到位的组合命令
如果想一次执行完成,可以用管道连接两个命令:
:%s/\([a-z]\)\([A-Z]\)/\1_\2/g | %s/.*/\U&/
原理说明
正则表达式中的重复捕获组(如\(...\)*)在反向引用时,只会返回最后一次匹配的结果,无法通过扩展反向引用来实现“每次匹配后添加下划线”的需求。因此采用“先插入分隔符,再统一转大写”的思路,能避开这个限制,更高效地完成转换。
内容的提问来源于stack exchange,提问作者leonyjiang
相关产品推荐
相关产品推荐

