Vim 修炼场
CHAPTER 02 · 移动篇 上

字符与词:让光标飞起来

预计阅读 40 分钟(含练习约 1 小时)· 前置:第 1 章(模式与 Esc)· 本章演示 7 个

学习目标

  • 彻底戒掉方向键:h j k l 成为手指的默认方向
  • 按词移动:w b e,以及大词版 W B E
  • 行首行尾瞬移:0 ^ $ g_
  • 行内直达任意字符:f F t T 与重复键 ; ,
  • 第一次体验「移动 = 动词的射程」:dt, 这样的组合句子
  • 建立本章的物理学直觉:一行之内,任何位置两键可达

1. 为什么专门用一章讲「移动」

回忆第 1 章的论断:写代码的大部分时间不在打字,在读、跳、改。而「读和跳」的本质是同一件事 —— 把光标送到目的地。移动是 Vim 里被使用频率最高的一类命令,没有之一;它也是后面一切的地基:第 5 章你会学到「删除的范围 = 移动的射程」,移动练不熟,编辑语言就永远说不利索。

方向键有三宗罪:

  • 远:在键盘右下角,每次去够,右手都要离开主键区,回来时还得重新定位(手指一离位,盲打就断);
  • 慢:一次一格,从行首到第 40 列要按 39 次;
  • 破坏节奏:手的位置一变,眼睛就得离开屏幕确认一下 —— 每次半秒,一天几百次。

本章的任务:让字符级移动(hjkl)接管方向键的职责,再给你三层越来越快的跳法 —— 按词、按行端、按字符直达。下一章再把战场扩大到整个文件(行与行之间的跳跃)。

先算一笔经济账。假设你每天在编辑器里做 300 次行内定位:鼠标方案 = 手离键盘 + 找指针 + 精确点击,平均 2.5 秒;方向键方案 = 平均 15 次按键 × 0.2 秒 = 3 秒,且右手来回搬家;本章的方案 = 平均 2 键 × 0.3 秒 ≈ 0.6 秒,手不离位、眼不离码。每天省下的十来分钟倒在其次,注意力不断线才是真正的收益 —— 光标听话之后,你才会开始「用移动思考」,而不是「用定位忍耐」。

2. h j k l:主键区的方向键

四个字母,画在键盘上正好是十字:

按键方向记法指法
h← 左十字最左右手食指(从 j 左移一格)
j↓ 下j 键上有小凸点,食指盲摸即知右手食指 home 位
k↑ 上十字最上右手中指
l→ 右十字最右右手无名指

注意演示里的计数前缀:先按 3 再按 j,一次跳三行。所有移动命令都吃数字前缀,这是 Vim「数格子交给机器」的第一课 —— 永远不要连按 8 次 l,要么 8l,要么干脆用下面更聪明的跳法。

💡 指法要点 右手食指永远「住」在 j 上(凸点就是家)。移动时只有手指动、手腕不动;如果你的手腕在键盘上平移,说明在「够」键 —— 那是旧习惯回来了。
💡 冷知识:为什么偏偏是 hjkl 1976 年 vi 诞生在 ADM-3A 终端上,那台机器的键盘上 hjkl 四个键位就印着方向箭头 —— Bill Joy 不是选了这四个键,是那台机器根本没有独立方向键。顺带一提:同一张键盘上,Esc 就印在今天 Tab 的位置 —— 这解释了为什么 Vim 的「回家」键是 Esc:当年它近在咫尺。历史锁定了布局,肌肉把它变成了效率。

怎么练:不要专门「背」,而是给自己立一条规矩 —— 接下来三天,方向键只准用于你还没学的场景(其实没有这种场景,所以等于禁用)。头半天会慢 30%,第二天追平,第三天开始反超。这是所有 Vim 学习者都走过的曲线,没有人例外。

3. 词的三兄弟:w b e

字符级移动是保底,真正的高频武器是词级。Vim 对「词」(word)的定义:连续的字母、数字、下划线算一个词;标点符号也各自成词 —— 连续的同类标点(比如 ) 后面跟 ; 不同类则分开,同类如 == 算一个)。听起来复杂,看一遍动画就懂:

按键含义什么时候用
w下一个词的开头最常用的前进键,「去下一个变量」
b上一个词的开头(back)往回找,w 的镜像
e当前/下一个词的结尾(end)要去词尾做事时(词尾加后缀、看边界)
ge上一个词的结尾冷门但有用:倒着按词尾走

决策法:问自己「我要去的其实是词的开头还是结尾?」 —— 开头用 w/b,结尾用 e。比如把光标放到一个函数名的最后一个字母上准备加后缀,e 一步到位;而「从行中间快速往左回到行首方向」,bbb 比 h×10 优雅得多。

用一个真实场景把三兄弟串起来:你在检查一行老代码 const total = price + tax;,想知道 total 是从哪来的 —— 光标停在行首,连按 w 逐个标识符「点名」;发现要看 price 的结尾有没有后缀,fp 直达后再 e 落在词尾;看完想回头核对 total,bbb(或 Ft 更快,下一节)。整个过程眼睛没离开过代码,手没离开过主键区 —— 这就是「用移动思考」的雏形。

至于词边界的精确规则,记住三条就够日常用了:①字母 / 数字 / 下划线互相粘连算一词(data_dir 是一个词);②标点同类粘连算一词(==、::、-> 各算一个);③字母和标点之间永远是边界(a,b 是三个词:a、逗号、b)。不确定的时候,在靶场里按 w 走一遍,眼睛会替你归纳 —— 比背规则快。

💡 心法 读代码时让眼睛当导航:「下一个标识符」= w;「刚才那个词是啥」= b。移动键的正确率,就是你对「词边界」的直觉本身。

4. 大词:W B E

「小词」把每个标点都当成独立单位,在代码里有时太碎 —— parse(data_dir, 里 w 要踩四五脚。大词(WORD)的定义粗暴得多:空白符(空格 / Tab)分隔的一切。于是 URL、路径、file.txt、a=>b 这种整体都算一个 WORD:

场景用小写(w/b/e)用大写(W/B/E)
逐个变量、逐个符号地看✅ 精细跳太快
跨过 foo(bar, 这种粘连片段要踩好几脚✅ 一步跨过
URL / 路径内部移动✅ 按 . / 分段整体一个词,一步出界

一句话决策:想「逐个标识符」走用小写,想「大步跨过标点海洋」用大写。Shift 顺手就有,不用白不用。

两个高频例子帮你建立体感:①光标在 https://example.com/api/v2 的开头,想走到 api:小写 w 要踩过 //、.、/ 一堆碎词,而大写 W 把整个 URL 当一个词,一步跳出界外再 b 回来反而快 —— 反过来,要在 URL 内部按段走,就得用小写;②一行模板字符串里嵌了好几处 ${...},用 W 按空白大步跳过插值块,比小写碎步清爽得多。大小写的切换,本质是在粒度之间换挡。

5. 行内瞬移:0 ^ $ g_

四个键,两两成对:行首一对(0 绝对 / ^ 非空白),行尾一对($ 绝对 / g_ 非空白):

按键落点典型场景
0(数字零)绝对行首,第 0 列要去缩进前面;配合可视化模式(ch07)
^第一个非空白字符代码里的"行首":到行首改代码用它
$行尾最后一个字符(含尾随空格)快去行尾;$ 后接 a = 手动版 A
g_最后一个非空白字符行尾有空格时,精确落在代码上
💡 最强助记:正则表达式 ^ 和 $ 正是正则里的行首 / 行尾锚点 —— vi 的作者直接借用了当时的惯例。写过一行正则的人,这两个键一辈子不会再忘:^const 匹配行首的 const,而 Vim 里 ^ 就是「跳到行首(第一个真字符)」。
💡 和第 1 章的连接 你已经会用 A(行尾插入)。现在拆开看:A = $ + a。快捷键不过是「移动 + 落笔」的打包 —— Vim 里到处都是这种「组合vs打包」的对应关系,理解了组合,打包键才不是死记。

代码场景里 ^ 的出场率远高于 0:大多数时候你要的是「这行代码从哪开始」,而不是「缩进前面那两个空格在哪」。什么时候才真需要 0?—— 要选中包含缩进的整行、或者检查缩进本身(空格还是 Tab、几个)的时候。一句话:看代码用 ^,看排版用 0。

6. 行内直达:f F t T 与 ; ,

本章最快的武器。f(find)后跟任意一个字符,光标直接送到本行下一处该字符上;t(till)则是送到目标前一格。大写 F/T 反向找。重复键 ;/, 沿同一目标继续前进 / 后退:

按键含义什么时候用
f+字符跳到本行下一处该字符上眼睛能看到目标行内的锚点字符
t+字符跳到该字符前一格目标是"字符之前的那段"(配合动词!)
F/T+字符同上,但往回找目标在光标左边时
; / ,重复刚才的 f/t:下一处 / 上一处一行里有多个同名锚点(逗号、点号)
⚠️ f 和 /(第 8 章)的分工 f 只在当前行内找,找不到就失败(光标不动,可能响一声铃);跨行查找是 / 的地盘,第 8 章讲。别用错工具。

几个实战细节:①目标在左边就用大写 F/T 反向找,比 b 猜词更精确;②一行里有重复字符时,先 f 一次再用 ; 踩点,别每次都重新按 fx —— 重复键存在的意义就是把三键变一键;③t 平时看起来只是 f 的「差一格版」,但配合动词时这一格就是护城河(下一节),所以别嫌它多余;④按错字符?f 之后按 Esc 取消待决,或直接再按一次对的字符前先 ; 会跳错 —— 习惯上,f 按错了就当无事发生,重新按就是,成本极低。

7. 移动即射程:dt, 的第一次合体

第 0 章预告过「动词 + 名词」。现在你手里的移动键,全都是现成的「名词」—— 给 d(删)当射程:

dt, = 「删,删到逗号前」。看懂这一步,你就看懂了 Vim 的核心机制:动词不自己带范围,范围由移动键给出。把 t, 换成 w 就是删一个词,换成 $ 就是删到行尾,换成 f; 就是删到下一个分号 —— 动词不变,射程随便换。第 5 章会把这套语法讲全,这里先把「移动很值钱」这件事刻进手感里。

给你三个今天就能用的「射程三连」,在靶场里各做五遍找感觉:dw(删掉光标往后一个词)、d$(删到行尾,也可以按 D —— 打包版)、df;(删到行内下一个分号,分号本身也删掉,和 dt, 只差「含不含终点」)。不用记结论,按一遍、撤销一遍,手感自然形成 —— u 就是你的免费回放键。

8. 行内组合拳:任何位置,两键以内

把本章的键合起来用,会得到一个很爽的性质:一行之内,光标从任何位置到任何位置,最多两三键。原理:先用 f/W/$/^ 做大跨度跳跃,再用 wehl 微调一格。

目标在哪首选微调
行首 / 行尾^ / $—(一击必中)
行内某个显眼字符附近f+字符hlwb
下一个标识符we 到词尾
跨过一段标点粘合物W / B; 接力
同字符多处(逗号、点)f+字符;; 踩点

组合的心法只有一条:先粗后细。大跨度交给 f/W/$/^,落地后如果差一格半格,再用 hlwe 微调。新手常见的顺序错误是反过来 —— 先一格一格挪到目标附近再犹豫 —— 那是方向键时代的肌肉记忆在作祟。练到后来,「两键到达」会变成一种条件反射:眼睛落在目标上的同时,手指已经出发。

9. 一句话处理折行:gj gk

如果编辑器开了软折行(wordWrap),一个逻辑行会折成多个屏幕行,此时 jk 走的是逻辑行,gj / gk 走屏幕行。写代码推荐直接关掉折行(见本章 IDE 备注),需要时再记这对前缀键不迟。

10. 每日训练计划(30 分钟 × 3 天)

本章内容建议拆三天消化,别一口气练完:

天时间盒内容通过标准
第 1 天0–10 分钟重放 7 个演示(单步),读 §1–§4能说出 w/b/e 各自落点
10–30 分钟练习 1 + 练习 2:hjkl 盲走 + w/e/b 词表全程不看键盘和手指
第 2 天0–10 分钟复习昨天的键,读 §5–§60/^/$/g_ 各落点张口就来
10–30 分钟练习 3:f 跳转游戏 + ; 连踩10 行代码不用方向键走完
第 3 天0–10 分钟读 §7–§8,重点体会 dt,能自己造 3 个「动词+射程」句子
10–30 分钟练习 4:两键挑战 + 盲测盲测 8/10,本章毕业

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

  1. 方向键退役:hjkl + 词级移动,手从此住进主键区;
  2. 眼睛看哪,光标就去哪:看到锚点字符就 f 它,看到词就 w 它 —— 不数格子;
  3. 移动就是射程:今天记住 dt, 这一个例子,第 5 章会还你一片森林。

下一章把战场从「一行」扩大到「整个文件」:相对行号、gg / G、段落跳跃、% 配对跳转 —— 光标开始在整个文件里飞。

练习

练习 1:hjkl 盲走网格(10 分钟)

靶场文件里随便找一块 10 行左右的代码,右手放在 j 凸点上,眼睛只看屏幕,用 hjkl 走出一个「口」字再走一个「之」字,最后走回起点。中途一旦手去摸方向键,从头再来。进阶:给自己计数,比如 5j3l,一次到位。

练习 2:w / e / b 词表朗读(10 分钟)

光标放到任意一行代码开头,连续 w 走到行尾,每按一次读出落点的标识符(不读标点也算过,读出来更好);再连续 b 走回行首;再 e 走一遍。三个键各走 10 行。你会自然记住「=、+、, 都是独立词」这个事实。

练习 3:f 跳转游戏 + ; 连踩(10 分钟)

找一行有多个逗号/点号的代码(比如参数列表),光标行首:f, 到第一个逗号,然后只用 ; 踩到行尾、只用 , 走回行首。再换 f.、f( 各来一轮。要点:; 长在手边,别每跳一次都重新按 f。

练习 4:两键挑战 + 盲测毕业考(10 分钟)

让同事(或自己随机)指定行内某个字符作为目标,要求最多两键把光标放上去,做 20 组。然后闭眼完成序列:^ → f; → ; → e → $ → bb → 0,睁眼检查光标位置是否符合预期,10 组对 8 组毕业。

常见陷阱

🕳 方向键复吸 头三天手指会「想念」方向键,一着急就伸手 —— 每次伸手都是一次退步。物理疗法:知道 macOS 可以在系统设置里把方向键临时禁用吗?狠人可以试;普通人至少在心里记一笔「刚才又够了」。
🕳 数格子上瘾 12l 这种精确数格子,说明还在用「字符思维」。代码里的目标是词和锚点字符,不是第 13 列:眼睛看到什么就用 w/f 去什么。计数前缀留给行数(下一章的 5j)。
🕳 在标点海洋里用 w 碎步 parse(data_dir, 里连按 w 踩四脚,不是你笨,是用错档位 —— 换 W 一步跨过。记住:小写=精细档,大写=越野档。
🕳 g_ 记不住就不记 行尾 99% 的场景 $ 够用;只有当行尾真有空白、且你要精确落在最后一个代码字符上时才需要 g_。忘掉它,需要时回来查这张表。

VSCode / IDEA 差异

VSCode(VSCodeVim)

  • 本章全部按键 VSCodeVim 原生支持,零额外配置
  • 建议关闭软折行,让 j/k 保持逻辑行语义:设置搜 editor.wordWrap 设为 off(默认就是 off)
  • Cmd←/→(行首/行尾)依然可用,但既然学了 ^/$,让它们退休
  • 下一章要用相对行号:现在就可以把 editor.lineNumbers 设为 relative(第 1 章配置里已有)

IntelliJ IDEA(IdeaVim)

  • IdeaVim 对本章按键同样全支持;f 查找还会有黄色高亮提示所有候选
  • 软折行同理:建议 Settings → Editor → General → Soft Wraps 不勾选代码场景
  • 开了折行的 Markdown 长段落,记得用 gj/gk 走屏幕行
  • 相对行号在 ~/.ideavimrc 里 set relativenumber(第 1 章配置已有,下一章讲为什么)

本章速记

按键作用按键作用
h j k l左 下 上 右0 / ^行首 / 首个非空白
w / b / e下一词头 / 上一词头 / 词尾$ / g_行尾 / 尾个非空白
W B E大词版(空白分隔)fx / tx到字符 x / 到 x 前一格
3j 等数字前缀 = 一次跳 N 格; / ,重复 f/t:下一处 / 上一处
gj / gk屏幕行上下(折行时)dt,删到逗号前(射程预告)

一句话心法:眼睛看到哪,光标就去哪 —— 词用 w,锚点用 f,行端用 0^$。