从一次重复劳动说起

上周处理一个遗留项目的代码迁移,需要将几百个这样的函数调用:

oldFunc(param1, param2, param3)

改成:

newFunc({
  arg1: param1,
  arg2: param2, 
  arg3: param3
})

手动改几个还行,几百个真是要命。这时候我想起了Vim的宏录制功能,结合文本对象,几分钟就搞定了。

宏录制的基础操作

很多人知道q键可以录制宏,但实际使用中总遇到各种问题。我总结了一个稳定的工作流:

  1. 定位到目标行 - 使用搜索/oldFunc快速定位
  2. 开始录制 - qq(录制到寄存器q)
  3. 执行操作序列
  4. 结束录制 - 按q
  5. 重复执行 - @q执行一次,10@q执行10次

文本对象的威力

真正让宏变得强大的是文本对象。在上述转换任务中,我是这样操作的:

qq                          " 开始录制
di(                         " 删除括号内的内容
newFunc({<CR>arg1: <Esc>    " 输入新函数开头
p                           " 粘贴刚才删除的内容
:s/, /,<CR>arg2: /g         " 替换分隔符
I  arg1: <Esc>              " 在行首插入缩进和arg1:
A,<CR>}<Esc>                " 在行尾添加逗号和花括号
:s/)/}/g                    " 替换括号
nq                          " 移动到下一个匹配项,结束录制

这里的di(就是文本对象的应用 - 删除括号内的所有内容。

常用文本对象速查

实际工作中这些文本对象最有用:

  • iw / aw - 单词(inner word / a word)
  • i" / a" - 引号内的内容
  • i( / a( - 圆括号内的内容
  • i[ / a[ - 方括号内的内容
  • i{ / a{ - 花括号内的内容
  • it / at - HTML/XML标签内的内容

宏调试技巧

宏录制最让人头疼的就是出错后不知道问题在哪。我常用的调试方法:

  1. 慢速回放 - 在录制时故意放慢速度,确保每个操作都正确
  2. 分步执行 - 录制短宏,然后用@@重复执行
  3. 查看寄存器 - :reg q查看录制的内容
  4. 编辑宏 - let @q = '新内容'直接修改出错的宏

实际案例:批量重命名

另一个常见场景是批量修改变量名。假设要把user_id改成userId

qq          " 开始录制
/user_id<CR>" 搜索目标
ciwuserId<Esc> " 修改当前单词
nq          " 搜索下一个,结束录制

然后使用100@q就能快速修改100个匹配项。

进阶技巧:条件执行

有时候我们想在宏执行到文件末尾时自动停止:

qq
// 你的操作序列
:if line('.') == line('$') | stopinsert | endif<CR>
q

这样当到达文件末尾时宏会自动停止,避免无意义的重复。

经验总结

经过多年的Vim使用,我发现宏成功的几个关键点:

  1. 先规划再录制 - 在纸上或注释里写好操作步骤
  2. 使用相对移动 - 避免使用绝对行号,用搜索和文本对象
  3. 测试小样本 - 先对3-5行测试,确认无误再批量执行
  4. 备份原文件 - 执行前:w保存,或者用版本控制

宏录制是Vim中最被低估的功能之一。一旦掌握,那些重复性的文本处理工作就会变得轻松愉快。希望这些实战经验对你有帮助!