你已经在 vimtutor 中练过 hjkl,但那只是"走"。真正的效率来自"跳"——一个命令跨越一个单词、一行、一个段落。Vim 的移动命令就是你的"步伐系统",步子越大,到达目标越快。
核心移动命令按范围从小到大排列:
| 范围 | 命令 | 作用 |
|---|---|---|
| 字符 | h j k l |
左 下 上 右 |
| 词 | w b e |
下个词 / 上个词 / 词尾 |
| 行 | 0 ^ $ |
行首 / 首个非空字符 / 行尾 |
| 文件 | gg G |
文件首行 / 文件末行 |
| 段落 | { } |
上段 / 下段(空行分隔) |
| 配对 | % |
跳到匹配的括号/引号 |
小写 w b e 以"标点也是词"的方式跳转,遇到 foo.bar() 会停在 . 和 () 处。大写 W B E 只以空格分隔,直接跳过 foo.bar() 整体。
3dw,缩进 4 行写 4>>。掌握了移动命令,现在把它和操作命令组合起来。Vim 的核心设计理念是"语法化操作"——就像自然语言有动词和名词,Vim 用动词(operator)+ 名词(motion)组成一条"指令句"。
三个核心 operator:
| 动词 | 含义 | 后续行为 |
|---|---|---|
d |
delete 删除 | 删后留在 Normal |
c |
change 修改 | 删后进入 Insert |
y |
yank 复制 | 不删,仅复制到寄存器 |
把它们和上一节的 motion 组合,就构成了完整的操作指令:
| 指令 | 拆解 | 效果 |
|---|---|---|
dw |
d + w | 删除到下个词开头 |
cw |
c + w | 删到下个词开头并进入 Insert |
d$ |
d + $ | 删除到行尾 |
yy |
y + y(整行) | 复制整行 |
cG |
c + G | 删到文件末尾并进入 Insert |
d% |
d + % | 删除括号内的全部内容 |
看到规律了吗?只要记住三个动词(d/c/y)和上一节的名词表,你就拥有了 3 x 7 = 21 种操作组合。加数字前缀还能扩展:2dw 删两个词,3yy 复制三行。这就是 Vim 语法的扩展性——不需要死记每个操作,掌握规则即可无限组合。
cw 直接输入新名,删一行用 dd 不进 Insert
motion 是"从光标走到目标"的路径,但有时候你不需要"走",而是要"圈一块区域"来操作。这就是文本对象(text object)——另一种"名词",直接指定目标范围,不需要移动光标。
文本对象的语法是 operator + i/a + 对象,其中 i 表示 inside(内部内容),a 表示 around(含外围)。
| 指令 | 效果 | 典型场景 |
|---|---|---|
ciw |
改光标所在词 | 重命名变量 |
da" |
删引号及内容 | 删除字符串参数 |
ci) |
改括号内内容 | 改函数参数列表 |
yi{ |
复制花括号内代码 | 复制函数体内容 |
cit |
改 HTML 标签内容 | 改 <p>...</p> 中间文字 |
假设你的代码是这样一行:result = calculate(width, height)。光标在 height 上时:
ciw 删除 height 并进入 Insert,直接输入新变量名
da( 删除 (width, height) 整组括号
ci) 删除括号内 width, height 并进入 Insert 重新输入参数
ci" 只删引号内的文字,引号保留;ca" 连引号一起删。在 "hello world" 中,ci" 删的是 hello world,ca" 删的是 "hello world" 含引号。当光标需要到达一个"你看得见但跳起来很远"的位置,逐词移动效率太低。搜索是 Vim 的第三种"名词"——输入关键词直接传送到目标位置。
搜索命令的核心语法:
| 命令 | 方向 | 作用 |
|---|---|---|
/keyword |
向下 | 搜索 keyword,回车跳转 |
?keyword |
向上 | 反向搜索 |
n |
同向 | 跳到下一个匹配 |
N |
反向 | 跳到上一个匹配 |
* |
向下 | 搜索光标所在词 |
# |
向上 | 反向搜索光标所在词 |
搜索支持正则表达式。/^func 搜索行首以 func 开头的行,/end$ 搜索行尾的 end。输入 :set hlsearch 可以高亮所有匹配结果,:noh 清除高亮。
替换是搜索的延伸,语法为 :s/旧/新/标志:
c 标志特别重要——加上它后每次替换会提示 y/n/a/q(是/否/全部/退出),避免误替换。批量重命名变量时强烈建议加 c 标志。
:%s/旧名/新名/gc
你用 y 复制的内容去了哪里?不是系统剪贴板,而是 Vim 的寄存器(register)——一个多插槽的存储系统。理解寄存器,你才能做到"复制 A,再复制 B,粘贴 A"这种操作。
寄存器就像一排带标签的抽屉,每个抽屉独立存放一段文本:
| 寄存器 | 名称 | 用途 |
|---|---|---|
"" |
无名寄存器 | y/d/x 默认存入此处 |
"0 |
yank 寄存器 | 只有 y 操作会写入,d/x 不覆盖 |
"a-"z |
命名寄存器 | 手动指定,长期保存 |
"+ / "* |
系统剪贴板 | 与外部程序共享 |
". |
最近插入文本 | 上次 Insert 模式输入的内容 |
使用命名寄存器的格式:"字母+操作。比如 "ayy 复制当前行到 a 寄存器,"ap 粘贴 a 寄存器的内容。
"+ 寄存器),不需要额外配置。在 Neovim 中 y 复制后直接在其他程序 Ctrl+V 粘贴。如果你发现剪贴板不互通,检查 Neovim 是否编译了 +clipboard 特性::checkclipboard。w b e 在词间跳转,感受小写和大写(W B E)的区别dw 删一个词,u 撤销,改用 cw 重做,观察进入 Insert 的区别/keyword 搜索文件中的函数名,按 n N 在匹配间跳转ci) 修改函数参数,用 da" 删除字符串:%s/旧变量/新变量/gc 批量重命名,逐个确认替换"a 寄存器,再复制另一段到 "b,分别用 "ap 和 "bp 粘贴dd)、修改变量名(ciw)、批量替换(:%s),全程不碰鼠标"+p,然后用 = 自动缩进格式化:b :vsp :tabnew 三大体系的使用方法。