Vim 修炼场
CHAPTER 13 · 集成与实战 下 · 毕业考

实战案例集:十二个真实重构场景

预计阅读 60 分钟(含拉练约 2 小时)· 前置:第 2–12 章 · 本章演示 12 个

学习目标

  • 在 12 个真实重构场景里把全书功夫串成组合拳:块选、文本对象、查找替换、寄存器、宏、:g 各就各位
  • 每个案例练成「意图 → 按键分解」的翻译能力:看到任务,十秒内报出按键序列
  • 建立成本意识:同一个任务的 vim 解法 vs 鼠标/IDE 原生解法,按键数与出错率各差多少,心里有账
  • 知道哪些活应该交给 IDE 原生(语义重构类)—— 会 vim 不是什么都自己按,是会选工具
  • 完成毕业拉练:把 12 个案例当靶场完整打一遍,计时验收

1. 怎么读这一章

前十二章是「学兵器」,这一章是「上阵」。每个案例的展开结构固定三段:任务与鼠标做法(先承认传统做法的痛点)、vim 按键分解(逐键说明,配动画)、成本对比(按键数是硬指标,出错率是软指标)。建议的读法:先看任务描述,自己心里默演一遍按键,再看分解和动画 —— 对上了,说明这一族工具你已真正消化;对不上,正好回对应章节补课。

先亮一下你的兵器谱,后面每个案例都是从中取件组装:

工具族代表按键擅长的问题形状出自
移动/射程w f gg * n「先到战场」—— 一两键抵达目标第 2、3、8 章
文本对象ciw ya" cit da(结构化指物:词、引号串、标签、括号对第 4 章
动词与语法d c y p ~ J说什么做什么的编辑语言第 5 章
可视化/块v V Ctrl-v I A眼见为实的范围、一切「列」形状第 7 章
查找替换/:g:s :%s//g :g//d按内容批量:一行命令一群行第 8 章
寄存器"0p "a "+ yy p内容的存取与搬运第 9 章
重复与宏. qa @a Ctrl-a做一次,重复 N 次第 10 章
IDE 特色gd gb F2 Cmd-d语义导航与多光标第 12 章

一条贯穿全章的提醒:案例里的按键序列不是「标准答案」,是一种合理组装。同一个任务,用 :s 还是 gb 还是宏,往往都行 —— 重要的是你能在几秒内挑出顺手且安全的那条路。安全优先级永远排在快前面:范围看不准就先选区圈地,语境拿不准就带 c 确认,批量做完先扫一眼再动下一步。

2. 案例① 行尾批量加分号(块选 $ A)

任务:三行语句漏了分号,行长不一。鼠标做法:每行「End 键 → 敲 ; → ↓」,三行九次击键外加视线在三行间往返;行数涨到二十行,就是六十次机械重复。vim 按键分解:Ctrl-v 起块 → jj 圈三行 → $ 把右边界拉到各自行尾(块模式特有语义,行长不一无所谓)→ A 块追加 → ; Esc 发货。七键,与行数无关地整齐:

成本账:7 键对 9+ 键只是起步,真正的差距在出错模式 —— 鼠标路线每一行都是独立决策,漏一行、多点一格都可能;块路线一次性圈定,眼睛确认一次。同类任务全归它:行尾去逗号($ 后 x)、行首统一加前缀(把 A 换 I)。IDE 的 Cmd-/ 管不了「加分号」这种自定义批量,这正是块选的独占领地。

3. 案例② 局部变量重命名(* + ciw + n .)

任务:函数内 cnt 改 count,共 3 处。鼠标做法:选中 → 改 → 找下一处 → 选中 → 改…… 或者赌一把全局替换伤到别处。vim 按键分解:* 把光标词设为查找词巡航一圈(顺便确认这 3 处都是同一变量,语境安全)→ N 回首处 → ciw count Esc 完成第一处 → 之后 n. n. 一鼓一槌:

成本账:11 键改完,且每一处都过目 —— n 跳过去的那眼既是确认也是保险。但必须划清边界(第 8 章 §9):这是文本级改名,适合局部变量、一次性脚本;真正的公共符号重命名,交给 IDE 的 F2 / Shift+F6 —— 语义级、跨文件、懂作用域。判断三秒:这个名字出不出这个文件?出,就 F2。

4. 案例③ 函数参数删除(f r + daw + x)

任务:调用处删掉 retry 参数。鼠标做法:数着引号定位 → 小心划选「retry、空格、逗号」三者之一 → 删 → 检查括号。vim 按键分解:fr 两键把光标钉上参数名(; 还能跳下一个 r)→ daw 吃掉「词 + 旁边空格」(a 版对象多带一口,第 4 章)→ 光标正好落在暴露的逗号上,x 收走。六键,括号配对、剩余参数无恙:

成本账:鼠标的痛点在「划选边界」,vim 的解法是让对象语法替你划。同族延伸:参数挪位置 = daw 后到目标位 p(行级思维照搬案例⑪);全清参数 = 光标放括号内 da( 一刀。改签名这件事,记得最后让 IDE 的重构菜单同步所有调用点 —— 单点手术 vim 快,全局联动 IDE 稳。

5. 案例④ 批量注释 / 取消注释(块选 I 与块删除)

任务:注释三行,验证完再取消。鼠标做法:拖选三行 → 找编辑器的注释按钮;取消再来一遍 —— 两头都要碰工具栏。vim 按键分解:注释 = Ctrl-v jj I // Esc(块插入,Esc 前只有一行显示,延迟满足);取消 = f/ 钉上注释符 → Ctrl-v jj 2l 圈住三列 → d 整块切掉:

成本账:注释 7 键、取消 9 键 —— 诚实地说,这个案例 IDE 原生 Cmd+/ 两键更省(选中即注释,再按即取消)。那为什么还练块选?三个理由:①它不挑语言,没有注释快捷键的环境(配置文件、日志、SQL 控制台)照样用;②块删除版能精确控制删几列(只删 // 留空格,或连空格一起);③中间只圈两行 = 选择性注释,Cmd-/ 只会整段全注。工具熟了,选择权在你。

6. 案例⑤ 提取字符串为常量(ya" + gg O + p + ci")

任务:把魔法字符串 "hello vim" 提成常量。鼠标:复制字符串 → 滚到文件头 → 开新行 → 打定义 → 粘贴 → 滚回来 → 划选替换,六段操作三次滚动。vim 按键分解:ya" 连引号复制 → gg 回文件头 → O 上开新行,打 const GREETING = Esc → p 把引号串贴进定义(寄存器隔着跳转依然保鲜,第 9 章)→ A 补分号 → j 回原行 f" ci" 换成 GREETING 引用:

成本账:20 键看着多,但每键都有明确职责、零滚动零找位置 —— 鼠标版的真实成本不在击键,在三次长距离导航打断思路。这个案例是「组合拳」的标本:ya" 是第 4 章、gg/O 是第 3/6 章、p 是第 9 章、ci" 是第 4 章 —— 没有新知识,只有组装。同族:提取数字常量(ya" 换 yiw)、提取函数名、上移一段代码(dap + kP)。IDE 的「Introduce Constant」重构一键完成且自动改所有引用 —— 单处提取用它;散落多处的手动提取,vim 组合拳更灵活。

7. 案例⑥ 日志语句批量清理(:g/console/d)

任务:提交前删掉函数里所有 console 行。鼠标:Cmd-f 搜 console → 删一行 → 下一个 → 删…… N 个回合。vim 按键分解:一条 :g/console/d 整批消失;u 一步反悔;精准版 :g/console\.time/d 只清计时打点(点号转义,第 8 章正则):

成本账:4 键清 3 行、40 行同样 4 键 —— 批量命令的威力在 N 上指数放大。它的安全感来自两头:执行前可以先用 :g/console 裸跑一遍(只列出匹配行不动手,「先侦查后开火」),执行后 u 整条回滚。同族存货:删空行 :g/^$/d、删注释行 :g/^\s*\/\//d、删调试块 :g/debug/normal dd(结合第 10 章 :normal)。日志清理的进阶版是让团队用构建开关替代手工删 —— 但那是另一个故事了。

8. 案例⑦ CSV 列提取(块选 y + 块粘贴)

任务:从四行 CSV(首行表头)里把 age 列提出来。鼠标:逐行划选那两三个字符 → 复制 → 粘贴,划选边界全靠眼睛量。vim 按键分解:光标放到数据区第一格(避开表头)→ Ctrl-v jj 圈三行 → 2l 拉宽到年龄列宽 → y 块复制 → G o Esc 表格下开行 → p 矩形粘贴,三行年龄自己站成一列:

成本账:9 键提一列,行数增加只改 j 的次数(或直接 3j)。块复制的独特价值:按几何列圈定,不管内容 —— 这正是多光标(按内容圈)与 :s(按模式圈)都做不好、或做起来很绕的形状。同族:日志剥时间戳前缀(块选 d)、对齐表格改列、从粘贴的对齐数据里抽字段。列形状,先想块。

9. 案例⑧ JSON 键值规范化(:%s 捕获组)

任务:JS 对象字面量转 JSON,键名要加双引号 —— name: 变 "name":,三处,值不能动。鼠标:逐个划选键名 → 打引号,几次下来眼花。vim 按键分解:一条 :%s/\(\w\+\):/"\1":/g —— 括号组 \(\w\+\) 抓住「词+冒号」里的键名,替换段 "\1" 把它原样放回再穿引号:

成本账:一条命令,键再多也是它。捕获组是「保留原文、只改包装」的通用语法(第 8 章讲过,这里兑现):反向剥引号 :%s/"\(\w\+\)":/\1:/g、给键加大写、日期改格式 :s/\(\d\+\)-\(\d\+\)-\(\d\+\)/\1年\2月\3日/…… 学的不是这一条命令,是「组捕获 + 回放」这个造句法。写完先看输出再 u,不放心加 c 逐处确认。

10. 案例⑨ 批量重命名编号(归零 + Ctrl-a 宏)

任务:三十行 id: 编号乱了,要重排成 1、2、3…… 鼠标:逐行删号重打,打完还要自查。vim 按键分解:两步走 —— ①归零::%s/id: \d\+/id: 0/ 全部清成 0;②生长:录宏 qa Ctrl-a j q(当前行 +1、下移),然后 28@a 连发:

成本账:准备工作一条命令 + 宏四键 + 连发三键,N 行编号总共不到十次击键。「归零再生长」是编号类任务的万能套路(第 10 章 §6):直接在乱序号上逐个改,每个都要看旧值算新值;归零后每行只做同一件事「+1」,才能交给宏连发。同族:批量生成测试数据(案例同款)、步长改 2 就在宏里多按一次 Ctrl-a、倒序编号用 Ctrl-x。

11. 案例⑩ HTML 标签改写(cit + ci")

任务:按钮文案改「提交订单」,类名 btn 改 btn-primary。鼠标:在标签里找文字边界划选替换,再眯着眼找 class 引号里那几个字母划选替换。vim 按键分解:光标随便在标签里一站 → cit(inner tag,改标签内容)打 提交订单 Esc → f" 钉上 class 引号 → ci"(改引号内)打 btn-primary Esc:

成本账:12 锋两刀,且完全不用数引号、找边界 —— it 和 i" 这两个对象把「标签的肉」和「属性的值」做成了名词,你只是在说「改它」。这是文本对象对结构化文本的碾压局:同族还有 ci<(改标签名)、dat(连标签带内容删)、配合 surround 的 cst(换标签,第 12 章)。前端同学把这一族练熟,划选标签内容的历史就结束了。

12. 案例⑪ 交换赋值语句(dd + p)

任务:width/height 两行声明顺序反了,交换。鼠标做法:拖拽或剪切粘贴 —— 手抖选多半行、粘错位置是常态。vim 按键分解:dd 删上行(行级删除进寄存器,第 9 章)→ p 粘到下方,三键交换完成:

成本账:3 键,零选择零拖拽 —— 行级「剪切粘贴」因为寄存器的形状语义(整行进、整行出、自动落位)而绝对精准。变体随手记:dd G p 挪到文件尾、dd P 粘到上方、kdd p 把下面那行提上来;词级交换是 xp(第 5 章)。「挪」这个高频动作,在 vim 里恒等于三键 —— 这是最先回本的投资之一。

13. 案例⑫ 只删函数内空行(V 选区 + :g/^$/d)

任务:f 函数内部有两个空行要清掉,但函数之间那个分隔空行必须保留 —— :%g/^$/d 会误伤全局。vim 按键分解:V jjjjj 行选圈住整个函数 → 按 :(自动带出 '<,'> 前缀,第 8 章)→ 补 g/^$/d 回车 —— 选区当 range,只清圈内的空行:

成本账:10 键,精确到「圈内的空行」。这个案例的含金量在两个体系的组合:V 圈地是第 7 章、:g/^$/d 是第 8 章、'<,'> 前缀是两者的接缝 —— 单独都会,接得上才是真会。同族:只在一个函数内做替换 :'<,'>s/old/new/g、只删函数内注释 :'<,'>g/^\s*\/\//d。「先圈地、再施工」永远比「全局开炮再后悔」稳。

14. 十二案例的规律:四句话总结

打完十二局,该复盘了。把案例按「用什么圈定范围」重新归类,规律就浮出来 —— Vim 的编辑难题本质上是「怎么圈」:圈法决定工具:

圈法工具本章案例
按结构圈(词、引号、标签、括号)文本对象② 改名、③ 参数、⑤ 提取、⑩ 标签
按几何圈(列、矩形)块选 Ctrl-v① 分号、④ 注释、⑦ 提列
按内容圈(模式、匹配行):s / :g⑥ 清日志、⑧ 规范化、⑫ 空行
按重复圈(做一次,来 N 次). / 宏 / Ctrl-a② 鼓点、⑨ 编号(①④是块,也可宏)

四句话带走:①结构能说清就不动手选(对象优先);②列形状交给块,别的工具都绕;③内容批量交给 :s/:g,先侦查后开火;④凡是重复,想 . 和宏。再加上那条安全边界 —— 语义级重构(F2 重命名、Introduce Constant)永远让 IDE 来 —— 你的工具选择器就完整了。

15. 毕业拉练计划(周末 2 小时)

阶段时间内容验收
上半场30 分钟案例①–⑥:每个案例在自己项目里找真实目标做一遍,对照动画核对按键每案例一次成功不返工
下半场30 分钟案例⑦–⑫ 同上;⑨ 的归零命令和 ⑫ 的选区前缀容易卡,慢就是快同上
计时赛20 分钟任选 6 个案例,每案例在自己造的靶场重打一遍并计时单案例 ≤30 秒
盲测40 分钟练习 4 的 12 题盲测 + 错题对应章节回炉12 题对 9 题,全站毕业 🎓

16. 如果本章只记住三件事

  1. 编辑难题 = 圈定范围:结构圈用对象、几何圈用块、内容圈用 :s/:g、重复圈用 . 和宏 —— 四种圈法定半生;
  2. 安全永远排在快前面:先 * 巡航再动手、选区圈地好过全局开炮、批量完 u 一步回滚、拿不准就带 c 确认;
  3. 会选工具比会按键盘重要:语义重构交给 IDE,文本批量留给自己 —— vim 的终点不是替代 IDE,是长在 IDE 里。

课程正文到此收官。接下来是附录:可打印的速查手册与常见问题 FAQ —— 日常干活时,它们比教程更常被翻开。

练习

练习 1:案例复刻(20 分钟)

挑 6 个案例(建议①②③⑥⑨⑫),每个在自己的真实代码里找一次对应场景照做。找不到就造靶:比如案例⑥在临时文件里粘 10 行 console。要求:每案例先默写按键序列再动手,与本章分解逐键核对。通过线:6 个案例全部一次成功,重做第二个案例时不用翻书。

练习 2:一题多解(15 分钟)

用「10 行行尾加分号」这个任务走四条路:①块选 $A(案例①);②A;Esc + j.×9(第 10 章);③录宏 qaA;Escjq + 9@a;④:%normal A;(第 10 章 §7)。每条路计时并记录手感。通过线:能说出四条路各自的适用边界(行长不一时谁占优?要跳过两行时谁最灵活?)。

练习 3:组合变式(15 分钟)

三个升级变式:①「案例⑫ + 案例⑧」:选区内把 foo 全改 bar(:'<,'>s/foo/bar/g);②「案例⑤ + 案例②」:提取常量后,用 * + n. 把其余出现处也换成常量;③「案例④ + 案例⑥」::g/console/normal I// 用 :g + :normal 给所有日志行加注释(不删只注释,提交前可逆)。通过线:变式按键序列自己能推出来 —— 拼装能力才是毕业证。

练习 4:毕业盲测(12 题)

先说按键序列再看答案:①20 行行尾加分号 ②局部变量 3 处改名 ③删一个参数 ④注释 5 行 ⑤提取字符串常量 ⑥删所有 console 行 ⑦CSV 抽一列 ⑧键名加引号 ⑨30 行编号重排 ⑩改标签文案 ⑪交换两行 ⑫删函数内空行。参考:①C-v 19j $ A ; Esc ②* N ciw n . n .(或 :%s//gc)③f 名 daw x(或 da( 全清)④C-v I // Esc(或 Cmd-/)⑤ya" gg O 打字 Esc p A ; Esc 回原处 ci" ⑥:g/console/d ⑦C-v 圈列 y G o Esc p ⑧:%s/\(\w\+\):/"\1":/g ⑨归零 :%s + qa Ctrl-a j q + 28@a ⑩cit / ci" ⑪dd p ⑫V 圈 + :'<,'>g/^$/d。12 对 9 题,全站毕业 🎓

常见陷阱

🕳 照抄按键不看语境,把教程用成模板 本章的按键序列绑定在演示的具体光标位置和代码形状上:案例③的 fr 只在 retry 是本行第一个 r 时成立,案例②的 n. 鼓点在出现点密集时才划算。学的是「圈法 + 组装」,不是字面序列 —— 换个文件就照抄,迟早翻车。动手前问一句:我的光标在哪?目标是什么形状?
🕳 追求一次到位,不给自己留后悔药 看完案例容易手痒直接放大招::%s 全文开炮、28@a 直接连发 —— 错一步就是 28 处错改。流程纪律:批量前先侦查(:g/pat 裸跑、* 巡航)、批量时留确认(c 标志、选区圈地)、批量后扫一眼再动(u 永远在)。快是结果,稳是前提。
🕳 该交 IDE 的活硬用 vim 文本技巧 案例②⑤的边界一定要守住:跨文件的公共符号重命名、带作用域分析的提取变量/内联,是 IDE 语义重构的主场 —— :%s 改公共 API 名会漏掉字符串里的引用、误伤同名局部变量。判断口诀:「名字出不出这个文件」 —— 出,就 F2/Shift+F6;不出,才轮到文本三件套。
🕳 块选前忘了检查行齐不齐 案例①的 $ 和案例⑦的固定列宽是两种对齐假设:前者「各行行长不同、都要到尾」,后者「各行该列起始位置相同」。CSV 有个别行多了一列、日志有时间戳长度不一,块就会圈歪 —— 动手前眼睛扫一遍目标列是否对齐,歪的行先修齐(或用 :s 按内容圈更稳)。

VSCode / IDEA 差异

VSCode(VSCodeVim)

  • 案例②的语义版:F2 重命名(跨文件);案例⑤的语义版:右键 → Refactor → Introduce Constant —— 语义场景优先这两个
  • 案例④:Cmd+/ 切换行注释两键搞定,块选版留作无快捷键环境与选择性注释
  • 案例②/⑩的多光标变式:gb 或 Cmd+d 逐个点名后一次改(第 12 章);案例⑦的列形状也可用 Cmd+Alt+↓ 加列光标
  • 案例⑥的 IDE 版:Cmd-Shift-f 全局搜 console 后逐个处理 —— 但删行批量仍是 :g/d 最快,两边配合用

IntelliJ IDEA(IdeaVim)

  • 案例②⑤的语义版:Shift+F6 重命名、Refactor → Introduce Field/Constant;案例③改签名用 Cmd+F6(Change Signature)自动同步所有调用点
  • 案例④:IDEA 注释快捷键 Cmd+/(行)/ Cmd+Shift+/(块);块选版价值同左列
  • 多光标 Alt+J(或第 12 章的 sethandler 配置);代码格式化 Cmd+Alt+L 可收编进 <Action> 映射挂 leader
  • 调试场景彩蛋:案例⑥的 console 清理,IdeaVim 里 :g/console/d 照用 —— :g 在 IDEA 的编辑器上同样整批生效

本章速记(十二案例一表收)

案例核心按键圈法案例核心按键圈法
① 补分号Ctrl-v $ A几何列⑦ 抽 CSV 列Ctrl-v y p几何列
② 改名* n .内容+重复⑧ 键规范化:%s/\(\w\+\):/"\1":/g内容
③ 删参数f名 daw x结构⑨ 编号重排归零 + Ctrl-a 宏重复
④ 注释Ctrl-v I(+Cmd+/)几何列⑩ 标签改写cit ci"结构
⑤ 提常量ya" ggO p结构+寄存器⑪ 交换两行dd p行级
⑥ 清日志:g/console/d内容⑫ 函数内空行:'<,'>g/^$/d内容+选区

一句话心法:结构圈用对象,几何圈用块,内容圈用 :s/:g,重复圈用 . 和宏;先侦查后开火,语义重构交 IDE。