5月27日 14:46

Vim 宏录制功能怎么用才能高效重复操作?

每天在 Vim 里重复同样的编辑动作,一遍又一遍地按键、移动、修改——如果有个按钮能把这串操作"录下来,一键回放",效率会怎样?Vim 的宏录制就是这样一个功能:它不是花架子,而是真正能省下大量重复劳动的工具。

宏录制的基本流程:q 开始,q 结束

宏的核心逻辑很简单:按 q 加一个寄存器名开始录制,再按 q 停止录制

具体步骤:

  1. 在普通模式下按 qa——把后续操作录制到寄存器 a 中,左下角会出现 recording @a 提示
  2. 执行你需要的编辑操作(移动、删除、插入、替换……任何普通模式命令都行)
  3. q 停止录制

仅此而已。录完后,寄存器 a 里就存好了你刚才的整个操作序列。

一个关键细节:录制前先把光标放到一个"干净"的位置。很多人第一次录宏时,光标在行中间就开始操作,结果回放时位置不对,整个宏就废了。养成习惯,录制前先按 0 回到行首,这样每次回放都从确定的位置开始。

回放宏:@ 和 @@

录好的宏用 @ 加寄存器名回放:

  • @a —— 执行寄存器 a 中的宏
  • @@ —— 重复执行上次回放的宏(不用再敲寄存器名)
  • 5@a —— 把宏执行 5 次

最实用的组合是:录好宏之后,先用 @a 跑一次确认效果没问题,然后直接 10@@50@@ 批量执行。如果中间某次执行出错(比如搜索没匹配到),宏会自动停止,不会一路错下去。

追加录制:用大写字母往宏里加步骤

录完宏发现漏了一步怎么办?不用重新录。按大写字母可以往已有宏的末尾追加操作

假设之前用 qa 录了一个宏,现在想在里面加一个操作:

  1. qA(大写 A)开始追加录制
  2. 执行你要补充的操作
  3. q 结束

这样寄存器 a 中的内容就是原来的操作加上新追加的操作。这在调试宏时特别有用——先录一个基础版本试跑,发现缺什么再追加。

宏寄存器:宏就是文本,可以查看和编辑

宏存储在 Vim 的命名寄存器(a-z)中,本质上就是一段按键序列的文本。这意味着你可以直接查看和修改它。

查看寄存器内容:

vim
:reg a

把宏粘贴出来编辑:

vim
"ap

这会把寄存器 a 的内容当作普通文本粘贴到当前光标位置。你直接改文本,改完再用 "ayy 把这一行存回寄存器 a。对于比较长的宏,这种编辑方式比重新录制快得多。

还有一个技巧:你可以在命令行直接设置寄存器内容:

vim
:let @a = '0iHello^[

其中 ^[ 是 Esc 键的表示,用 Ctrl+V 然后 Esc 输入。这样你甚至可以把宏写成配置文件的一部分。

批量执行::normal 命令配合可视模式

逐行 @a 效率太低,Vim 提供了两种批量执行宏的方式。

方式一:用次数前缀

vim
5@a

简单直接,但要确保文件确实有足够的行,否则宏在中途找不到目标行会报错停止。

方式二:可视模式 + :normal

  1. 可视模式选中目标行(V 然后 jG
  2. 输入 :normal @a

这种方式更稳妥——只在你选中的行上执行,不会跑飞。而且即使某一行执行出错,其他行照常执行,互不影响。处理大文件时,这个特性非常关键。

方式二的进阶用法:对整个文件执行宏。

vim
:%normal @a

等价于先 ggVG 全选再 :normal @a,但写法更简洁。

复杂宏技巧:计数、搜索与递归

宏不只是一堆简单的移动和编辑命令,它完全可以包含搜索、计数等高级操作。

在宏中使用搜索

录制时按 /pattern<CR> 搜索目标位置,回放时宏会自动执行这个搜索。这对于"找到下一个符合条件的位置再操作"的场景非常有效。

但要注意:搜索命令在不同行可能匹配到不同位置。如果你的操作依赖精确的列位置,搜索后最好加一个 0^ 把光标规范到行首。

计数器递增

Vim 有个 Ctrl+A 命令可以让光标下的数字加 1。结合宏可以快速生成递增序列:

  1. 在第一行输入 1
  2. qa 开始录制
  3. yy 复制当前行,p 粘贴到下一行
  4. Ctrl+A 让数字加 1
  5. q 结束录制
  6. 98@a 生成 1 到 100

递归宏:让宏自己调用自己

在录制宏的最后一步,输入 @a(调用自身),然后再按 q 结束录制。这样宏就会不断递归执行,直到某一步出错自动停止。

vim
qa " 开始录制到 a 0 " 移到行首 /pattern " 搜索目标 dd " 删除该行 @a " 递归调用自身 q " 结束录制

递归宏适合处理"不确定有多少行需要操作"的情况——不用先数行数再决定执行几次,它会一直跑到搜索失败为止。

宏的持久化:让宏在重启后仍然可用

默认情况下,宏只存在于当前 Vim 会话中,退出就没了。要让宏持久化,有几种方式:

方式一:写入 vimrc

vim
let @a = '0dwelp'

把宏内容直接写进配置文件,每次启动 Vim 自动加载。

方式二:使用 viminfo

Vim 默认会将寄存器内容写入 viminfo 文件,下次启动时恢复。确认你的 vimrc 中有:

vim
set viminfo='100,<50,s10,h,rA:,rB:

其中 '100 表示保存最近 100 个文件的信息,包括寄存器。

方式三:保存到文件

vim
:call writefile([@a], 'my_macro.txt')

下次要用时:

vim
:let @a = readfile('my_macro.txt')[0]

这种方式适合在不同机器间共享宏。

常见应用场景

批量给行加引号

vim
qa " 录制到 a I" " 行首插入引号 Esc A" " 行尾插入引号 Esc j " 下一行 q " 结束 :%normal @a " 全文执行

CSV 数据提取

从一行数据中提取特定列,删掉其余部分:

vim
qa " 录制 0df, " 删到第一个逗号 2f,ld$ " 定位到第三列,删到行尾 j " 下一行 q " 结束

代码批量重命名

把所有 old_method 替换成 new_method,同时保留行尾注释:

vim
qa " 录制 0/new_method" 搜索 cwnew_method " 替换 Esc j " 下一行 q " 结束

当然简单替换用 :%s/old_method/new_method/g 更快,但宏的优势在于可以同时处理更复杂的组合操作——比如替换后还要调整缩进、移动位置、插入新行等,这些 :s 命令做不到。

Markdown 表格对齐

vim
qa " 录制 0f|lxA " 删除多余空格 Esc f|lxA " 下一列同样操作 Esc j " 下一行 q " 结束

宏与点命令的区别

很多人会问:已经有了 .(重复上一次修改),为什么还要宏?

两者的核心区别:

特性点命令 .@a
记录范围只记录一次修改记录完整操作序列
是否包含移动不包含包含
能否保存不能存在寄存器中
能否编辑不能可以
适用场景单一修改的重复多步操作的重复

简单说,dot 适合"同一修改,多处应用";宏适合"同一套操作流程,多行执行"。如果你的重复操作里只有一步修改,用 .;如果有移动、搜索、多次修改的组合,用宏。


Vim 的宏录制不是什么高深技巧,但它是从"手动重复"到"自动化编辑"的关键一步。核心就三件事:q 开始录、@ 回放、可视模式批量执行。掌握这三点,大部分重复编辑场景都能应对。遇到更复杂的需求,再考虑追加录制、递归宏、寄存器编辑这些进阶手法。录宏时记住一个原则——让每一步操作都位置无关,这样回放时才不会跑偏。

标签:Vim