Vim命令最全用法指南
Vim 命令最全用法指南
本文旨在成为最全面的 Vim 中文参考手册,涵盖从入门到高级的所有核心用法。
目录
- Vim 简介与安装
- Vim 的四种模式详解
- 移动与导航命令
- 插入与编辑命令
- 删除与剪切命令
- 复制、粘贴与寄存器
- 查找与替换
- 可视化模式
- 多文件编辑(Buffer / Window / Tab)
- 分屏操作
- 标记与跳转
- 文本对象(Text Objects)
- 宏录制与回放
- 命令行模式与 Ex 命令
- Vim 配置(.vimrc)
- 插件管理
- 常用插件推荐
- Vim 与 NeoVim 的区别
- Vim 模式在其他工具中的应用
- 高级技巧与工作流
- 实战场景合集
- 故障排查与常见问题
- 常用速查表
1. Vim 简介与安装
1.1 什么是 Vim?
Vim(Vi IMproved)是 Bram Moolenaar 于 1991 年创建的文本编辑器,是 Unix 经典编辑器 vi 的增强版。它的核心设计哲学是完全键盘操作——双手无需离开主键位即可完成所有编辑工作。
Vim 的主要特点:
- 模态编辑:不同的模式对应不同的操作(Normal、Insert、Visual 等)
- 无处不在:Linux/macOS 系统自带,SSH 远程开发必备用
- 极高的编辑效率:熟练后编辑速度远超鼠标操作
- 强大的扩展性:支持脚本、插件、自定义配置
- 语言生态:几乎所有编程语言都有对应的 Vim 插件
1.2 安装 Vim
Ubuntu / Debian
sudo apt update
sudo apt install vim
CentOS / RHEL / Fedora
sudo yum install vim # CentOS/RHEL
sudo dnf install vim # Fedora
macOS
# macOS 自带的是精简版 vim,建议通过 Homebrew 安装完整版
brew install vim
Arch Linux
sudo pacman -S vim
Windows
- 方式一:从 vim.org 下载安装包
- 方式二:使用 Scoop:
scoop install vim - 方式三:使用 Chocolatey:
choco install vim - 方式四:使用 WSL(推荐):在 WSL 中
sudo apt install vim
从源码编译(启用所有功能)
git clone https://github.com/vim/vim.git
cd vim/src
make distclean
./configure --with-features=huge --enable-python3interp --enable-cscope --enable-gui=gtk3
make
sudo make install
验证安装
vim --version
输出示例(关键信息):
VIM - Vi IMproved 9.1 (2024 Jan 02, compiled ...)
Included patches: 1-XXX
Compiled by root@hostname
Huge version without GUI. Features included (+) or not (-):
+acl +cscope +job +python3
+autocmd +cursorbind +jumplist +quickfix
...
注意:确保
+clipboard、+python3、+lua等特性为+,否则某些功能(如系统剪贴板)无法使用。
1.3 Vim vs Vi
| 特性 | Vi | Vim |
|---|---|---|
| 撤销 | 只能撤销一次 | 无限撤销 |
| 模式 | 3 种 | 6+ 种 |
| 分屏 | 不支持 | 支持 |
| 插件 | 不支持 | 支持 |
| 语法高亮 | 不支持 | 支持 |
| 脚本 | 不支持 | Vimscript |
| 可视模式 | 不支持 | 支持 |
1.4 第一次启动 Vim
vim # 打开空白 Vim
vim filename # 打开(或创建)文件
vim +42 file # 打开文件并跳转到第 42 行
vim +/pattern f # 打开文件并跳转到第一个匹配 pattern 的位置
vim -R file # 只读模式打开
vim -d f1 f2 # diff 模式比较两个文件
vim -O f1 f2 # 垂直分屏打开两个文件
vim -o f1 f2 # 水平分屏打开两个文件
vim -p f1 f2 f3 # 以 Tab 页方式打开三个文件
应用场景:SSH 登录服务器后需要快速编辑配置文件,vim /etc/nginx/nginx.conf 即可开始编辑。
2. Vim 的四种模式详解
Vim 的核心设计是模态编辑——同一个按键在不同模式下含义完全不同。这是 Vim 学习曲线的最大障碍,但也是其效率的根源。
2.1 Normal 模式(普通模式)
用途:浏览代码、执行命令、删除/复制/粘贴文本。这是 Vim 的默认模式,也是你大部分时间应该在的模式。
进入方式:
- Vim 启动时默认进入 Normal 模式
- 在任何其他模式下按
Esc回到 Normal 模式
" 在 Normal 模式下按 x 删除光标处字符
" 在 Normal 模式下按 dd 删除整行
应用场景:你正在浏览代码,需要快速跳转到某个函数定义。在 Normal 模式下输入 :/function_name 即可搜索。
💡 核心原则:让手保持在主键位(home row),大部分操作都在 Normal 模式下完成。
2.2 Insert 模式(插入模式)
用途:输入文本,和普通编辑器一样。
进入方式(从 Normal 模式):
| 命令 | 含义 | 光标位置 |
|---|---|---|
i |
在光标前插入 | 当前字符前 |
I |
在当前行开头插入 | 行首非空字符 |
a |
在光标后插入 | 当前字符后 |
A |
在当前行末尾插入 | 行尾 |
o |
在下方新开一行插入 | 新行 |
O |
在上方新开一行插入 | 新行 |
s |
删除当前字符并插入 | 删除处 |
S |
删除当前行并插入 | 行首 |
gi |
在上次插入位置插入 | 上次离开 Insert 的位置 |
gI |
在第一列插入 | 第 0 列 |
示例:
假设光标在单词 "hello" 的 'e' 上:
i → 在 'h' 和 'e' 之间插入
a → 在 'e' 和 'l' 之间插入
I → 跳到行首 'h' 前插入
A → 跳到 'o' 后插入
o → 在下一行插入
O → 在上一行插入
退出方式:
Esc:回到 Normal 模式Ctrl-[:等同于 Esc(不用够到 Esc 键)Ctrl-C:强制回到 Normal 模式(不触发 InsertLeave 自动命令)
Insert 模式下的特殊键:
| 按键 | 功能 |
|---|---|
Ctrl-h |
删除前一个字符(等同 Backspace) |
Ctrl-w |
删除前一个单词 |
Ctrl-u |
删除到行首 |
Ctrl-t |
缩进(向右移一个 shiftwidth) |
Ctrl-d |
反缩进(向左移一个 shiftwidth) |
Ctrl-n |
自动补全(向下搜索) |
Ctrl-p |
自动补全(向上搜索) |
Ctrl-r |
插入寄存器内容 |
Ctrl-o |
执行一个 Normal 命令后返回 Insert |
Ctrl-a |
插入上次插入的文本 |
应用场景:写代码时,o 快速在下方新建一行开始写,比用鼠标点击行尾再回车快得多。
2.3 Visual 模式(可视化模式)
用途:选中文本后进行操作(类似鼠标选中)。
| 命令 | 含义 |
|---|---|
v |
字符级可视化选择 |
V |
行级可视化选择 |
Ctrl-v |
块级可视化选择(矩形选择) |
gv |
重新选中上次的选择区域 |
选中后可执行的操作:
| 操作 | 命令 |
|---|---|
| 删除 | d 或 x |
| 复制(拉取) | y |
| 替换 | c |
| 替换字符 | r |
| 大写 | U |
| 小写 | u |
| 翻转大小写 | ~ |
| 缩进 | > |
| 反缩进 | < |
| 自动缩进 | = |
| 查找 | /(在选中范围内) |
| 保存到文件 | :w filename(选中部分另存为) |
| 外部命令过滤 | ! |
应用场景:选中一段代码后按 > 缩进,或按 = 自动格式化。
2.4 Command-Line 模式(命令行模式)
用途:输入 Ex 命令(以 : 开头)、搜索(/ 或 ?)、过滤(!)。
进入方式:
:→ Ex 命令模式/→ 向下搜索?→ 向上搜索!(Visual 模式下)→ 外部命令过滤
示例:
:w 保存
:wq 保存并退出
:q! 不保存退出
:%s/old/new/g 全文替换
:!ls 执行 shell 命令 ls
命令行模式下的编辑键:
| 按键 | 功能 |
|---|---|
Tab |
自动补全命令/文件名 |
Ctrl-r |
插入寄存器 |
Ctrl-w |
删除前一个单词 |
Ctrl-u |
删除到行首 |
Ctrl-b / Home |
光标移到行首 |
Ctrl-e / End |
光标移到行尾 |
↑ / ↓ |
浏览命令历史 |
2.5 替换模式(Replace Mode)
| 命令 | 含义 |
|---|---|
R |
进入替换模式(覆盖已有字符) |
r{char} |
替换当前字符为 {char},自动回到 Normal |
gR |
虚拟替换模式(不影响 Tab 展开对齐) |
示例:
原文:Hello World
光标在 'H' 上,按 R,输入 "HI" → HI llo World
光标在 'H' 上,按 rH → 不变
光标在 'H' 上,按 rA → Aello World
应用场景:快速修正打错的几个字符而不需要进入 Insert 模式。
2.6 模式切换关系图
┌──────────┐
Esc │ Normal │ ← 默认模式
┌──────────────→│ │←──────────────┐
│ └────┬─────┘ │
│ │ │
│ i I a A o O s S gi │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ Esc │ Insert │ │
│ ┌────────────→│ │ │
│ │ └──────────┘ │
│ │ │
│ │ v V Ctrl-v │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────┐ Esc │
│ │ │ Visual │────────────────────────────┘
│ │ │ │
│ │ └──────────┘
│ │ ┌──────────┐
│ │ │Command │
│ └───── : / ? ───────→│ Line │─── Esc ──→ Normal
│ └──────────┘
│
└──────────────────────────────────────────
记忆口诀:Esc 是万能回 home 键——任何时候不知道在什么模式,按两下 Esc 回到 Normal。
3. 移动与导航命令
Vim 的移动命令极其丰富,掌握它们是高效编辑的基础。
3.1 基本移动(字符级)
| 命令 | 含义 | 助记 |
|---|---|---|
h |
左 | ← |
j |
下 | ↓ (j 像向下的钩子) |
k |
上 | ↑ |
l |
右 | → |
↑ k
← h l →
↓ j
数字前缀:5j = 向下移动 5 行,10l = 向右移动 10 个字符。
💡 提示:方向键也可以用,但在 Vim 哲学中,h/j/k/l 效率更高。很多 Vim 高手会在
.vimrc中禁用方向键来强迫自己学习。
3.2 单词级移动
| 命令 | 含义 | 说明 |
|---|---|---|
w |
下一个单词开头 | word - 以标点和空格分隔 |
W |
下一个 WORD 开头 | 以空格分隔(更粗粒度) |
b |
上一个单词开头 | back |
B |
上一个 WORD 开头 | |
e |
下一个单词结尾 | end |
E |
下一个 WORD 结尾 | |
ge |
上一个单词结尾 | |
gE |
上一个 WORD 结尾 |
word vs WORD 的区别:
foo_bar baz_qux
w的移动路径:foo→_→bar→baz→_→qux(6 步)W的移动路径:foo_bar→baz_qux(2 步)
应用场景:
- 写代码时
w更精确(可以停在每个变量名部分) - 写文章时
W更高效(跳过整个词组)
3.3 行内移动
| 命令 | 含义 | 说明 |
|---|---|---|
0 |
行首 | 数字 0,绝对的第一个字符 |
^ |
第一个非空字符 | 跳过行首空格/Tab |
$ |
行尾 | |
g_ |
最后一个非空字符 | |
_ |
第一个非空字符(同 ^) | 带计数:N_ 跳到第 N 行 |
| ` | ` | 第 N 列 |
+ |
下一行首个非空字符 | |
- |
上一行首个非空字符 |
示例:
def hello_world():
pass
- 光标在
hello的e上 0→ 跳到行首(d前的空格处第 0 列)^→ 跳到d(第一个非空字符)$→ 跳到)后的行尾
3.4 字符查找(行内)
| 命令 | 含义 |
|---|---|
f{char} |
向后查找字符 {char},光标停在该字符上 |
F{char} |
向前查找字符 |
t{char} |
向后查找字符 {char},光标停在其前一个字符 |
T{char} |
向前查找字符 {char},光标停在其后一个字符 |
; |
重复上次 f/F/t/T 查找 |
, |
反向重复上次 f/F/t/T 查找 |
示例:
const result = calculate_sum(a, b, c, d, e)
- 光标在行首
c(const 的 c) f(→ 跳到(f,→ 跳到第一个,;→ 跳到第二个,dt)→ 删除从光标到)前的所有内容(删除参数)
应用场景:修改函数参数时,f( 快速跳到括号处,ci( 直接修改括号内所有内容。
3.5 括号匹配
| 命令 | 含义 |
|---|---|
% |
跳到匹配的括号 ()、[]、{} |
示例:
if (condition) {
do_something();
}
- 光标在
{上,按%→ 跳到} - 光标在
(上,按%→ 跳到)
应用场景:快速检查括号是否匹配,或者在函数的开头和结尾之间跳转。
3.6 屏幕级移动
| 命令 | 含义 |
|---|---|
H |
跳到屏幕顶部(High) |
M |
跳到屏幕中部(Middle) |
L |
跳到屏幕底部(Low) |
Ctrl-f |
向下翻一页(Forward / Page Down) |
Ctrl-b |
向上翻一页(Backward / Page Up) |
Ctrl-d |
向下翻半页(Down) |
Ctrl-u |
向上翻半页(Up) |
Ctrl-e |
屏幕向下滚动一行(光标不动,文字下移) |
Ctrl-y |
屏幕向上滚动一行 |
zt |
当前行移到屏幕顶部 |
zz |
当前行移到屏幕中部 |
zb |
当前行移到屏幕底部 |
应用场景:
- 看长函数时用
Ctrl-d/Ctrl-u翻半页浏览 zz把当前行移到屏幕中间,方便查看上下文
3.7 文件级移动
| 命令 | 含义 |
|---|---|
gg |
跳到文件第一行 |
G |
跳到文件最后一行 |
:N 或 NG |
跳到第 N 行(如 42G 或 :42 跳到第 42 行) |
50% |
跳到文件 50% 处 |
:0 |
跳到第 0 行(文件开头,同 gg) |
:$ |
跳到最后一行(同 G) |
3.8 跳转与回退
| 命令 | 含义 |
|---|---|
Ctrl-o |
跳回上一个位置(older) |
Ctrl-i |
跳到下一个位置(newer,与 Tab 相同) |
` ` |
在上次跳转的两个位置之间切换 |
' . |
跳到上次修改的行 |
`. |
跳到上次修改的确切位置 |
`" |
跳到上次退出文件时的位置 |
`^ |
跳到上次 Insert 模式的位置 |
示例:
1. 你在第 10 行编辑代码
2. 用 :100 跳到第 100 行查看定义
3. 按 Ctrl-o 回到第 10 行
4. 按 Ctrl-i 再次回到第 100 行
应用场景:在多文件之间跳转查看定义后快速回到编辑位置,Ctrl-o 是最常用的导航命令之一。
3.9 其他移动命令
| 命令 | 含义 |
|---|---|
( |
上一句(以 ./?/! 分隔) |
) |
下一句 |
{ |
上一段(以空行分隔) |
} |
下一段 |
[[ |
上一节(以 { 在第一列分隔) |
]] |
下一节 |
[] |
上一节的末尾 |
][ |
下一节的开头 |
:# |
跳到第 # 列 |
应用场景:在写 Markdown 或文章时,} 快速跳到下一段,{ 跳到上一段。
4. 插入与编辑命令
4.1 所有插入方式
(已在 2.2 节详细介绍,这里做汇总)
| 命令 | 含义 | 场景 |
|---|---|---|
i |
光标前插入 | 在现有文字中插入 |
I |
行首插入 | 在行开头加注释/修饰符 |
a |
光标后插入 | 在字符后追加内容 |
A |
行尾追加 | 最常用的追加方式 |
o |
下方新行插入 | 在当前行后新建一行 |
O |
上方新行插入 | 在当前行前新建一行 |
s |
删字符插入 | 修改打错的字符 |
S |
删行插入 | 重写整行 |
gi |
上次插入位置 | 继续上次编辑 |
gI |
第 0 列插入 | 在绝对行首插入 |
4.2 数字与插入命令组合
数字可以与插入命令组合,实现批量操作:
3iHello Esc → 插入 "HelloHelloHello"(3 次重复)
3o Esc → 新建 3 个空行
5a- Esc → 在光标后插入 5 个 "-"
⚠️ 注意:在 Insert 模式下按 Esc 才会触发重复,Vim 会重复你从进入 Insert 到退出之间输入的所有内容。
4.3 Insert 模式下的便捷操作
| 按键 | 功能 | 场景 |
|---|---|---|
Ctrl-r = |
计算表达式并插入 | Ctrl-r = 然后 3*4 Enter → 插入 12 |
Ctrl-r " |
插入未命名寄存器(上次删除/复制) | 快速粘贴 |
Ctrl-r 0 |
插入 yank 寄存器 | 粘贴复制的文本 |
Ctrl-r + |
插入系统剪贴板 | 粘贴外部内容 |
Ctrl-r a |
插入寄存器 a | 插入命名寄存器内容 |
Ctrl-o |
执行一个 Normal 命令后返回 Insert | Ctrl-o $ 跳到行尾继续输入 |
示例:在 Insert 模式下需要快速插入计算结果:
按 i 进入 Insert
按 Ctrl-r =
输入 1024*768
按 Enter
→ 插入 "786432"
应用场景:写文档时需要插入一个计算结果,不必退出 Insert 模式去算。
5. 删除与剪切命令
5.1 基本删除
| 命令 | 含义 |
|---|---|
x |
删除光标处字符(等同 dl) |
X |
删除光标前字符(等同 dh) |
dd |
删除整行(剪切到寄存器) |
D |
删除到行尾(等同 d$) |
d0 |
删除到行首 |
d^ |
删除到行首非空字符 |
dw |
删除一个单词 |
dW |
删除一个 WORD |
daw |
删除一个单词(含周围空格) |
diw |
删除一个单词(不含空格) |
de |
删除到单词末尾 |
dE |
删除到 WORD 末尾 |
db |
删除到单词开头 |
dgge |
删除到上一个单词末尾 |
dgg |
删除到文件开头 |
dG |
删除到文件末尾 |
d) |
删除到下一句开头 |
d} |
删除到下一段开头 |
dt{char} |
删除到字符 {char} 前 |
df{char} |
删除到字符 {char}(含该字符) |
d% |
删除到匹配的括号 |
5.2 数字组合
数字前缀可以让删除命令执行 N 次:
3x → 删除 3 个字符
3dd → 删除 3 行(剪切 3 行)
d3w → 删除 3 个单词
d5j → 删除当前行和下面 5 行
d10G → 删除从当前行到第 10 行
d.,$ → 删除从当前位置到文件末尾
5.3 撤销与重做
| 命令 | 含义 |
|---|---|
u |
撤销(undo) |
Ctrl-r |
重做(redo) |
U |
撤销对当前行的所有修改 |
g- |
以前的撤销状态 |
g+ |
较新的撤销状态 |
5.4 行合并与拆分
| 命令 | 含义 |
|---|---|
J |
合并下一行到当前行(用空格连接) |
gJ |
合并下一行到当前行(不加空格) |
i Enter |
在插入模式下换行 |
示例:
合并前:
Hello
World
光标在 "Hello" 行,按 J →
合并后:
Hello World
应用场景:从 PDF 网页复制的文本经常被人为断行,用 J 快速合并。
5.5 特殊删除
| 命令 | 含义 |
|---|---|
:g/^$/d |
删除所有空行 |
:g/^\s*$/d |
删除所有空白行(含空格/Tab) |
:g/pattern/d |
删除所有包含 pattern 的行 |
:v/pattern/d |
删除所有不包含 pattern 的行 |
:%d |
删除整个文件内容 |
应用场景:处理日志文件时 :g/DEBUG/d 删除所有 DEBUG 级别日志。
6. 复制、粘贴与寄存器
6.1 基本复制粘贴
| 命令 | 含义 |
|---|---|
yy 或 Y |
复制当前行(yank) |
yw |
复制一个单词 |
y$ |
复制到行尾 |
y0 |
复制到行首 |
yG |
复制到文件末尾 |
ygg |
复制到文件开头 |
p |
在光标后粘贴 |
P |
在光标前粘贴 |
gp |
粘贴并将光标移到粘贴内容末尾 |
gP |
粘贴并将光标移到粘贴内容开头 |
示例:
第 1 行:Hello
第 2 行:World
- 光标在第 1 行,
yy复制 "Hello" p粘贴 → "Hello" 出现在第 2 行(下一行)P粘贴 → "Hello" 出现在第 1 行(上一行)
6.2 数字组合
3yy → 复制 3 行
5p → 粘贴 5 次
y3w → 复制 3 个单词
ytp → 复制到字符 'p' 前
yfp → 复制到字符 'p'(含 p)
6.3 寄存器(Registers)
寄存器是 Vim 的剪贴板系统。Vim 不只有一个剪贴板,而是有多个命名寄存器。
寄存器类型
| 寄存器 | 名称 | 说明 |
|---|---|---|
" |
未命名寄存器 | 默认存放最近一次删除/复制的内容 |
0 |
yank 寄存器 | 专门存放最近一次复制的内容 |
:delmarks! |
删除所有 a-z 标记 |
应用场景:编辑大文件时,用 ma 在函数定义处设标记,编辑完后 `a 快速跳回。用 mA 设置全局标记,在多文件间跳转。
12. 文本对象(Text Objects)
文本对象是 Vim 中最强大的功能之一。它允许你对"语义单元"(单词、句子、段落、括号内容等)进行操作。
12.1 语法
[count] {operator} {a|i} {object}
a= around(包含周围的分隔符/空格)i= inside(不包含分隔符)
12.2 文本对象列表
| 对象 | i (inside) |
a (around) |
说明 |
|---|---|---|---|
w |
iw 词内 |
aw 词+周围空格 |
word |
W |
iW WORD内 |
aW WORD+周围空格 |
WORD |
s |
is 句内 |
as 句+周围空格 |
sentence |
p |
ip 段内 |
ap 段+周围空行 |
paragraph |
t |
it 标签内 |
at 含标签 |
HTML/XML tag |
( 或 ) 或 b |
i( 括号内 |
a( 含括号 |
parentheses |
[ 或 ] |
i[ |
a[ |
square brackets |
{ 或 } 或 B |
i{ |
a{ |
curly braces |
< 或 > |
i< |
a< |
angle brackets |
' |
i' |
a' |
single quotes |
" |
i" |
a" |
double quotes |
` |
i` |
a` |
backticks |
, |
i, |
a, |
comma-separated (vim 8.2+) |
12.3 与操作符组合
| 组合 | 含义 |
|---|---|
ciw |
修改当前单词(change inside word) |
caw |
修改当前单词(含空格) |
di( |
删除括号内的内容 |
da( |
删除括号及其内容 |
ci" |
修改引号内的内容 |
ca" |
修改引号及其内容 |
di{ |
删除花括号内的内容 |
cit |
修改 HTML 标签内的内容 |
dat |
删除整个 HTML 标签 |
yi[ |
复制方括号内的内容 |
viB |
选中花括号内的内容(含大括号) |
=i{ |
格式化花括号内的代码 |
>ip |
缩进当前段落 |
示例:
假设光标在括号内的任意位置:
call_function(arg1, arg2, arg3)
↑ 光标在这里
ci( → 清空括号内容并进入 Insert 模式
结果: call_function()
(光标在 () 内,Insert 模式)
di( → 删除括号内容
结果: call_function()
da( → 删除括号及内容
结果: call_function
(括号也没了)
假设光标在引号内:
name = "John Doe"
↑ 光标在这里
ci" → 清空引号内容并插入
结果: name = ""
(Insert 模式)
di" → 删除引号内容
结果: name = ""
HTML 标签操作:
<div class="container">Hello World</div>
↑ 光标在这里
cit → 修改标签内容
结果: <div class="container"></div>
(Insert 模式)
cat → 删除整个标签
结果: (整行消失)
dat → 同上,删除整个标签
应用场景:
- 写代码时
ci(修改函数参数 - 写 HTML 时
cit修改标签内容 - 写 JSON 时
ci"修改字符串值 di{删除代码块内容
12.4 自定义文本对象
你可以通过插件或 Vimscript 创建自定义文本对象:
" 示例:创建下划线文本对象(如 snake_case_variable)
" 需要 vim-textobj-user 插件
call textobj#user#plugin('underscore', {
\ '-': {
\ 'select-i': 'i_',
\ 'select-a': 'a_',
\ }
\ })
13. 宏录制与回放
宏是 Vim 的杀手级功能——录制一系列操作并重复执行。
13.1 录制与回放
| 命令 | 含义 |
|---|---|
q{register} |
开始录制到寄存器 |
q |
停止录制 |
@{register} |
执行寄存器中的宏 |
@@ |
重复执行上次的宏 |
{N}@{register} |
执行宏 N 次 |
:reg {register} |
查看寄存器中的宏内容 |
13.2 录制示例
场景:给一系列行添加引号
原始:
apple
banana
cherry
date
操作:
1. 光标到第一行行首(gg)
2. qa → 开始录制到寄存器 a
3. I" → 在行首插入引号
4. Esc
5. A" → 在行尾追加引号
6. Esc
7. j → 移动到下一行
8. q → 停止录制
9. 3@a → 对下面 3 行重复执行
结果:
"apple"
"banana"
"cherry"
"date"
场景:给一系列数字加 1
原始:
1. First item
2. Second item
3. Third item
操作:
1. 光标到第一个数字上
2. qa → 开始录制
3. Ctrl-a → 数字加 1(变成 2)
4. j → 下一行
5. q → 停止
6. 2@a → 执行 2 次
结果:
2. First item
3. Second item
4. Third item
13.3 递归宏
递归宏利用 Vim 的特性:当宏在执行过程中调用自己时,会形成递归,直到不能执行为止。
场景:删除所有空行
1. qa → 开始录制到 a
2. /\<CR> → 搜索空行(这里 \< 代表空行匹配,实际用 /^$)
实际操作:
qa
/^$<CR>
dd
q
3. 这时寄存器 a 内容为:/^$<CR>dd
4. 999@a → 执行 999 次
每次执行:搜索空行 → 如果找到就 dd 删除 → 继续下一次
如果搜索失败(没有空行了),宏自动停止
⚠️ 递归宏要求:宏内部必须包含会失败的搜索/移动作为终止条件。
13.4 编辑宏
宏存储在寄存器中,可以像编辑文本一样编辑宏:
1. :put a → 将寄存器 a 的内容粘贴到当前行下方
2. 编辑这一行的内容(修改宏)
3. 0 "ay$ → 将修改后的行重新存入寄存器 a
4. dd → 删除这一行
应用场景:录制的宏有细微错误,不必重新录制,直接编辑宏内容即可。
13.5 多行执行宏
方法一:在 Visual 模式下选择行,然后 :normal @a
1. V 选中所有要执行宏的行
2. :normal @a
→ Vim 对每行执行宏 a
方法二:用 :g 命令
:g/pattern/normal @a " 对所有匹配 pattern 的行执行宏 a
:%normal @a " 对所有行执行宏 a
方法三:用行范围
:5,20normal @a " 第 5-20 行执行宏 a
14. 命令行模式与 Ex 命令
14.1 文件操作
| 命令 | 含义 |
|---|---|
:w |
保存 |
:w file |
另存为 |
:w! |
强制保存(覆盖只读) |
:w >> file |
追加到文件 |
:q |
退出 |
:q! |
强制退出(不保存) |
:wq 或 :x |
保存并退出 |
ZZ |
保存并退出(Normal 模式快捷键) |
ZQ |
不保存退出(Normal 模式快捷键) |
:wa |
保存所有 |
:wqa |
保存所有并退出 |
:qa! |
强制退出所有 |
:e file |
打开文件 |
:e! |
重新加载当前文件(放弃修改) |
:e# |
编辑上一个文件 |
:r file |
读取文件内容插入到当前行下方 |
:saveas file |
另存为并切换到新文件 |
14.2 外部命令
| 命令 | 含义 |
|---|---|
:!{cmd} |
执行 shell 命令 |
!!{cmd} |
用命令输出替换当前行 |
:r !{cmd} |
读取命令输出并插入 |
:{range}!{cmd} |
用命令过滤指定行 |
:%!{cmd} |
用命令过滤整个文件 |
:sh |
临时进入 shell(exit 回到 Vim) |
:terminal |
在 Vim 内开终端(Vim 8+) |
示例:
:!ls -la " 查看 当前目录
:!python3 % " 运行当前 Python 文件(% 代表当前文件名)
:!make " 执行 make
:r !date " 插入当前日期
:r !cal " 插入日历
:r !seq 1 10 " 插入 1-10 的数字序列
:%!sort " 全文排序
:%!jq . " 用 jq 格式化 JSON
:5,10!sort " 第 5-10 行排序
:'<,'>!python3 -m json.tool " 格式化选中的 JSON
!!date " 用 date 输出替换当前行
应用场景:
:%!jq .格式化 JSON 文件:%!column -t对齐 CSV 列:r !git log --oneline -5插入最近的 Git 提交记录
14.3 行范围操作
| 范围 | 含义 |
|---|---|
:1,5d |
删除第 1-5 行 |
:.,$d |
删除从当前行到末尾 |
:1,.d |
删除从开头到当前行 |
:/foo/,/bar/d |
删除从 foo 到 bar 之间的行 |
:/^+/-1 |
当前行减 1 |
:'a,'bd |
从标记 a 到标记 b 删除 |
Ex 命令(行操作):
| 命令 | 含义 |
|---|---|
:{range}d |
删除 |
:{range}y |
复制 |
:{range}t{addr} |
复制到 {addr} 行下方(copy/co/t) |
:{range}m{addr} |
移动到 {addr} 行下方(move/mo) |
:{range}s/old/new/g |
替换 |
:{range}normal {cmds} |
对每行执行 Normal 模式命令 |
:{range}join |
合并行 |
示例:
:5,10t20 " 将第 5-10 行复制到第 20 行下方
:5,10m20 " 将第 5-10 行移动到第 20 行下方
:5,10m0 " 将第 5-10 行移到文件开头
:'<,'>t. " 复制选中区域到当前行下方
:%normal I// " 每行行首加 //
14.4 映射(Mapping)
| 命令 | 含义 |
|---|---|
:map lhs rhs |
所有模式映射 |
:nnoremap lhs rhs |
Normal 模式递归映射(推荐) |
:vnoremap lhs rhs |
Visual 模式映射 |
:inoremap lhs rhs |
Insert 模式映射 |
:cnoremap lhs rhs |
Command 模式映射 |
:noremap lhs rhs |
所有模式非递归映射 |
:nunmap lhs |
取消 Normal 映射 |
:nmap |
查看所有 Normal 映射 |
:imap |
查看所有 Insert 映射 |
💡 建议:始终使用
noremap系列(非递归),避免递归映射导致的无限循环。
特殊键表示:
| 按键 | 表示法 |
|---|---|
<CR> |
Enter |
<Esc> |
Escape |
<Tab> |
Tab |
<Space> |
空格 |
<BS> |
Backspace |
<C-x> |
Ctrl-x |
<M-x> |
Alt-x(Meta) |
<S-x> |
Shift-x |
<F1>-<F12> |
功能键 |
<Leader> |
mapleader 变量(默认 \) |
<LocalLeader> |
局部 leader |
映射示例:
" 按 jk 快速退出 Insert 模式
inoremap jk <Esc>
" Leader + w 保存
nnoremap <Leader>w :w<CR>
" Leader + q 退出
nnoremap <Leader>q :q<CR>
" 快速拆分窗口
nnoremap <Leader>vs :vsplit<CR>
nnoremap <Leader>sp :split<CR>
" 快捷编辑 vimrc
nnoremap <Leader>ev :vsplit $MYVIMRC<CR>
nnoremap <Leader>sv :source $MYVIMRC<CR>
14.5 缩写(Abbreviation)
| 命令 | 含义 |
|---|---|
:iab lhs rhs |
Insert 模式缩写 |
:ab lhs rhs |
所有模式缩写 |
:cab lhs rhs |
Command 模式缩写 |
:una lhs |
取消缩写 |
:ab |
查看所有缩写 |
示例:
:iab @@ user@example.com " 输入 @@ 自动替换为邮箱
:iab teh the " 自动纠错
:iab tnx thanks " 快速输入
:cab W w " 防止 :W 报错(大小写)
💡 缩写只在输入完整词后输入非词字符(空格/标点/Enter)时触发。
14.6 其他常用 Ex 命令
| 命令 | 含义 |
|---|---|
:version |
显示 Vim 版本信息 |
:help {topic} |
打开帮助文档 |
:set {option} |
设置选项 |
:syntax on |
开启语法高亮 |
:filetype on |
开启文件类型检测 |
:colorscheme {name} |
切换配色方案 |
:source {file} |
执行 Vimscript 文件 |
:redir > file |
将命令输出重定向到文件 |
:silent {cmd} |
静默执行命令 |
:echo {expr} |
显示消息 |
:echom {expr} |
显示消息(记录到历史) |
:messages |
查看消息历史 |
:retab |
将 Tab 转为空格(或反向) |
15. Vim 配置(.vimrc)
15.1 .vimrc 的位置
| 系统 | 路径 |
|---|---|
| Linux/macOS | ~/.vimrc |
| Windows | $HOME/_vimrc 或 $VIM/_vimrc |
| NeoVim | ~/.config/nvim/init.vim 或 init.lua |
15.2 基础配置
" ============================================
" Vim 基础配置
" ============================================
" --- 基本行为 ---
set nocompatible " 关闭 vi 兼容模式
set encoding=UTF-8 " 编码设为 UTF-8
set fileencoding=UTF-8 " 文件编码
set backspace=indent,eol,start " Backspace 正常工作
" --- 显示 ---
set number " 显示行号
set relativenumber " 显示相对行号(推荐!)
set cursorline " 高亮当前行
set cursorcolumn " 高亮当前列
set showmatch " 高亮匹配的括号
set matchtime=2 " 括号匹配高亮持续时间(0.1秒单位)
set scrolloff=5 " 光标上下保留 5 行可见
set sidescrolloff=5 " 左右滚动保留 5 列
set wrap " 自动换行
set linebreak " 智能换行(不在单词中间断开)
set showcmd " 显示输入的命令
set wildmenu " 命令行补全菜单
set laststatus=2 " 始终显示状态栏
set ruler " 显示光标位置
set signcolumn=yes " 始终显示标志列
" --- 缩进 ---
set autoindent " 自动缩进
set smartindent " 智能缩进
set tabstop=4 " Tab 显示为 4 个空格宽
set shiftwidth=4 " 缩进宽度 4
set softtabstop=4 " Tab/Backspace 处理 4 个空格
set expandtab " Tab 转为空格
set shiftround " 缩进对齐到 shiftwidth 的倍数
set smarttab " 在行首时合理处理 Tab
" --- 搜索 ---
set incsearch " 增量搜索(边输边搜)
set hlsearch " 高亮搜索结果
set ignorecase " 忽略大小写
set smartcase " 智能大小写(有大写时不忽略)
" --- 文件处理 ---
set autoread " 文件被外部修改时自动读取
set autowrite " 切换 buffer 时自动保存
set hidden " 允许隐藏未保存的 buffer
set backup " 创建备份文件
set undofile " 持久化撤销历史
set undodir=~/.vim/undodir " 撤销历史目录
set swapfile " 交换文件(防止崩溃丢失)
set updatecount=100 " 每 100 字符更新交换文件
" --- 编辑体验 ---
set mouse=a " 启用鼠标
set clipboard=unnamedplus " 系统剪贴板(Linux)
set splitright " 新窗口在右边
set splitbelow " 新窗口在下面
set timeoutlen=1000 " 按键序列超时
set ttimeoutlen=50 " 键码序列超时
set updatetime=300 " CursorHold 触发时间(ms)
set virtualedit=block " 可视块模式可越过行尾
set whichwrap=b,s,<,>,[,] " 方向键可跨行
set completeopt=menu,menuone,noselect " 补全菜单设置
" --- 性能 ---
set lazyredraw " 执行宏时不重绘
set regexpengine=0 " 正则引擎(0=自动, 1=旧, 2=NFA)
set ttyfast " 快速终端连接
" --- 视觉 ---
syntax on " 语法高亮
filetype plugin indent on " 文件类型检测
colorscheme desert " 配色方案
15.3 快捷键映射
" 修改 Leader 键
let mapleader = " "
let maplocalleader = "\\"
" 退出
nnoremap <Leader>q :q<CR>
nnoremap <Leader>w :w<CR>
nnoremap <Leader>x :x<CR>
nnoremap <Leader>Q :qa!<CR>
" 窗口切换
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
" Buffer 切换
nnoremap <S-l> :bn<CR>
nnoremap <S-h> :bp<CR>
nnoremap <Leader>d :bd<CR>
" 快速 ESC
inoremap jk <Esc>
inoremap kj <Esc>
" 取消搜索高亮
nnoremap <Esc> :nohlsearch<CR>
" 快速移动
nnoremap J 5j
nnoremap K 5k
nnoremap H ^
nnoremap L $
" 选中整个文件
nnoremap <Leader>a ggVG
" 快速重载 vimrc
nnoremap <Leader>sv :source $MYVIMRC<CR>
" 快速编辑 vimrc
nnoremap <Leader>ev :vsplit $MYVIMRC<CR>
" 复制到系统剪贴板
vnoremap <Leader>y "+y
nnoremap <Leader>y "+y
nnoremap <Leader>Y "+Y
" 从系统剪贴板粘贴
nnoremap <Leader>p "+p
nnoremap <Leader>P "+P
" 上下移动选中行
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
" 缩进后保持选中
vnoremap < <gv
vnoremap > >gv
15.4 自动命令(autocmd)
" 文件类型相关设置
augroup filetype_settings
autocmd!
autocmd FileType python setlocal tabstop=4 shiftwidth=4 expandtab
autocmd FileType javascript setlocal tabstop=2 shiftwidth=2 expandtab
autocmd FileType html setlocal tabstop=2 shiftwidth=2 expandtab
autocmd FileType css setlocal tabstop=2 shiftwidth=2 expandtab
autocmd FileType markdown setlocal wrap spell
autocmd FileType yaml setlocal tabstop=2 shiftwidth=2 expandtab
autocmd FileType json setlocal tabstop=2 shiftwidth=2 expandtab
augroup END
" 进入/离开窗口时切换相对行号
augroup toggle_relative
autocmd!
autocmd BufEnter,FocusGained * set relativenumber
autocmd BufLeave,FocusLost * set norelativenumber
augroup END
" 保存时自动去除行尾空格
augroup trim_whitespace
autocmd!
autocmd BufWritePre * %s/\s\+$//e
augroup END
" 自动创建目录
augroup auto_mkdir
autocmd!
autocmd BufWritePre * call mkdir(expand('<afile>:p:h'), 'p')
augroup END
15.5 常用配色方案
| 配色 | 说明 |
|---|---|
desert |
Vim 自带经典配色 |
slate |
Vim 自带深色配色 |
molokai |
流行的 TextMate 风格配色 |
gruvbox |
暖色系,保护视力 |
solarized |
经典的 Solarized 配色 |
dracula |
暗色主题 |
nord |
北欧风格冷色系 |
tokyonight |
Tokyo Night 主题 |
catppuccin |
柔和的配色 |
onedark |
Atom 风格配色 |
安装第三方配色:
# 方式一:直接下载到 colors 目录
mkdir -p ~/.vim/colors
curl -o ~/.vim/colors/gruvbox.vim https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim
# 方式二:通过插件管理器安装(推荐,见第 16 节)
16. 插件管理
16.1 Vim 8 原生包管理
Vim 8+ 内置了包管理功能,不需要任何第三方插件管理器。
目录结构:
~/.vim/pack/
├── {pack-name}/ " 任意名称的包(如 "myplugins")
│ ├── start/ " 启动时自动加载的插件
│ │ ├── plugin-a/
│ │ └── plugin-b/
│ └── opt/ " 按需加载的插件
│ ├── plugin-c/
│ └── plugin-d/
安装插件:
# 安装 surround 插件
mkdir -p ~/.vim/pack/plugins/start
git clone https://github.com/tpope/vim-surround.git ~/.vim/pack/plugins/start/vim-surround
# 安装 commentary 插件
git clone https://github.com/tpope/vim-commentary.git ~/.vim/pack/plugins/start/vim-commentary
# 按需加载插件(:packadd plugin-name 才加载)
git clone https://github.com/preservim/nerdtree.git ~/.vim/pack/plugins/opt/nerdtree
管理命令:
:packadd {plugin} " 手动加载可选插件
:packl " 加载所有 start 插件
:helptags ALL " 为所有插件生成帮助标签
更新插件:
# 进入每个插件目录执行 git pull
for dir in ~/.vim/pack/*/start/*/; do
(cd "$dir" && git pull)
done
16.2 vim-plug 插件管理器
vim-plug 是最流行的 Vim 插件管理器,轻量且高效。
安装:
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
配置(在 .vimrc 中):
call plug#begin('~/.vim/plugged')
" --- 基础插件 ---
Plug 'tpope/vim-sensible' " 合理的默认设置
Plug 'tpope/vim-surround' " 操纵环绕字符(括号/引号/标签)
Plug 'tpope/vim-commentary' " 快速注释 gcc
Plug 'tpope/vim-repeat' " 让 . 命令支持插件操作
Plug 'tpope/vim-fugitive' " Git 集成
Plug 'tpope/vim-unimpaired' " 常用配对快捷键
" --- 文件浏览 ---
Plug 'preservim/nerdtree' " 文件树
Plug 'Xuyuanp/nerdtree-git-plugin' " NERDTree Git 标记
" --- 模糊搜索 ---
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim' " FZF 集成
" --- UI 增强 ---
Plug 'vim-airline/vim-airline' " 状态栏
Plug 'vim-airline/vim-airline-themes'
Plug 'ryanoasis/vim-devicons' " 文件图标
" --- LSP 和补全 ---
Plug 'neoclide/coc.nvim', {'branch': 'release'} " CoC 补全
" --- 语法和语言 ---
Plug 'sheerun/vim-polyglot' " 多语言语法包
Plug 'dense-analysis/ale' " 异步 Lint 引擎
" --- 编辑增强 ---
Plug 'junegunn/vim-easy-align' " 对齐
Plug 'terryma/vim-multiple-cursors' " 多光标
Plug 'godlygeek/tabular' " 文本对齐
Plug 'matze/vim-move' " 上下移动行
" --- 主题 ---
Plug 'morhetz/gruvbox'
Plug 'dracula/vim', { 'as': 'dracula' }
call plug#end()
vim-plug 命令:
:PlugInstall " 安装所有 Plug 声明的插件
:PlugUpdate " 更新所有插件
:PlugClean " 删除未声明的插件
:PlugUpgrade " 更新 vim-plug 自身
:PlugStatus " 查看插件状态
:PlugDiff " 查看更新差异
16.3 其他插件管理器
| 管理器 | 特点 |
|---|---|
| vim-plug | 最流行,简单易用,并行安装 |
| packer.nvim | NeoVim 专用,Lua 配置 |
| Vundle | 老牌管理器,已不太维护 |
| Pathogen | 最早的管理器,简单直接 |
| dein.vim | 高性能,按需加载 |
17. 常用插件推荐
17.1 必装插件
| 插件 | 功能 | 常用命令 |
|---|---|---|
| vim-surround | 操纵环绕字符 | cs"' ds" ysw" |
| vim-commentary | 快速注释 | gcc gc gcap |
| vim-repeat | 增强 . 命令 | 支持插件操作的重复 |
| vim-fugitive | Git 集成 | :G :Gstatus :Gdiff |
| fzf.vim | 模糊搜索 | :Files :Rg :Buffers |
17.2 vim-surround 详解
" old text" → 在引号内任意位置
cs"' " 改为双引号:"old text"
cs'<q> " 改为 <q> 标签:<q>old text</q>
cst" " 标签改回引号:"old text"
ds" " 删除引号:old text
ysw) " 给下一个单词加圆括号:(old) text
yss) " 给整行加圆括号:(old text)
S<div> " 可视模式下用标签包围
17.3 vim-commentary 详解
gcc " 注释/取消注释当前行
gc " 可视模式:注释选中区域
gcip " 注释当前段落
gcap " 注释当前段落
gcG " 注释到文件末尾
:7,10Commentary " 注释第 7-10 行
17.4 vim-fugitive 详解
:G " 打开 Git status(类似 git status)
:Gstatus " 同上
:Gdiff " 显示与 HEAD 的差异
:Gblame " 显示 Git blame
:Gcommit " Git commit
:Gpush " Git push
:Gpull " Git pull
:Glog " Git log
:Gread " git checkout -- file(恢复文件)
:Gwrite " git add file(暂存文件)
:Gmove " git mv
:Gremove " git rm
:Gbrowse " 在浏览器中打开当前行
在 :Gstatus 窗口中:
-= 暂存/取消暂存
|U|D|D|p| |
17.5 fzf.vim 详解
:Files " 模糊搜索文件
:Buffers " 搜索已打开的 buffer
:Lines " 在所有 buffer 中搜索行
:Rg pattern " 用 ripgrep 搜索内容
:GFiles " Git 跟踪的文件
:GFiles? " Git status 文件
:History " 最近的文件
:Commands " 搜索 Vim 命令
:Helptags " 搜索帮助文档
:Snippets " 搜索代码片段
:Marks " 搜索标记
:Windows " 搜索窗口
:Colors " 搜索配色方案
" 推荐映射
nnoremap <Leader>f :Files<CR>
nnoremap <Leader>b :Buffers<CR>
nnoremap <Leader>g :Rg<CR>
nnoremap <Leader>l :Lines<CR>
nnoremap <Leader>h :History<CR>
17.6 其他推荐插件
| 插件 | 说明 |
|---|---|
| vim-easy-align | 轻松对齐文本:gaip= |
| vim-multiple-cursors | 多光标编辑 |
| vim-move | Alt-j/Alt-k 上下移动行 |
| auto-pairs | 自动补全括号/引号 |
| vim-snippets | 代码片段集合 |
| ultisnips | 代码片段引擎 |
| tagbar | 标签栏(需要 ctags) |
| indentLine | 显示缩进线 |
| vim-tmux-navigator | Vim 和 tmux 无缝切换 |
| vim-devicons | 文件类型图标 |
| nvim-treesitter | NeoVim 语法解析(超强的语法高亮) |
| telescope.nvim | NeoVim 模糊搜索(FZF 的替代) |
| nvim-lspconfig | NeoVim LSP 配置 |
| nvim-cmp | NeoVim 补全引擎 |
| gitsigns.nvim | Git 标记(增删改行标记) |
| which-key.nvim | 显示可用快捷键提示 |
18. Vim 与 NeoVim 的区别
18.1 NeoVim 简介
NeoVim(Nv)是 Vim 的现代化分支,由 Thiago de Arruda 于 2014 年发起。目标是改进代码质量、可扩展性和嵌入能力。
18.2 主要区别
| 特性 | Vim | NeoVim |
|---|---|---|
| 配置语言 | Vimscript | Vimscript + Lua |
| 内置终端 | :terminal(Vim 8+) |
内置终端(一等公民) |
| LSP 支持 | 需要插件(CoC/ALE) | 内置 LSP 客户端 |
| 异步任务 | job_start()(Vim 8+) |
更完善的异步 API |
| Tree-sitter | 不支持 | 内置支持 |
| UI | 终端 UI | 可分离 UI(GUI/Web/终端) |
| 插件 API | Vimscript | Lua API + Vimscript |
| 启动速度 | 快 | 更快(Lua 配置) |
| 内置补全 | Ctrl-n/p |
内置 LSP 补全 |
18.3 NeoVim 配置
-- ~/.config/nvim/init.lua
-- 基础设置
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.smartindent = true
vim.opt.wrap = false
vim.opt.incsearch = true
vim.opt.hlsearch = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes"
vim.opt.clipboard = "unnamedplus"
-- Leader 键
vim.g.mapleader = " "
-- 快捷键
vim.keymap.set("n", "<leader>w", ":w<CR>")
vim.keymap.set("n", "<leader>q", ":q<CR>")
vim.keymap.set("i", "jk", "<Esc>")
vim.keymap.set("n", "<C-h>", "<C-w>h")
vim.keymap.set("n", "<C-j>", "<C-w>j")
vim.keymap.set("n", "<C-k>", "<C-w>k")
vim.keymap.set("n", "<C-l>", "<C-w>l")
18.4 选择建议
- 新手:先学 Vim,掌握基础后再考虑切换
- SSH 远程开发:Vim 足够(无需额外安装 NeoVim)
- 本地开发:推荐 NeoVim(LSP、Tree-sitter 体验更好)
- 已有 Vim 配置:NeoVim 兼容
.vimrc,可以平滑迁移
19. Vim 模式在其他工具中的应用
Vim 的模态编辑理念影响了大量工具,很多工具都支持 Vim 快捷键。
19.1 VS Code Vim 插件
安装 VS Code 的 Vim 插件(由 VSCodeVim 团队开发)后,几乎所有的 Vim 快捷键都可以使用。
常用配置(settings.json):
{
"vim.easymotion": true,
"vim.incsearch": true,
"vim.useSystemClipboard": true,
"vim.useCtrlKeys": true,
"vim.hlsearch": true,
"vim.insertModeKeyBindings": [
{ "before": ["j", "k"], "after": ["<Esc>"] }
],
"vim.normalModeKeyBindingsNonRecursive": [
{ "before": ["<leader>", "w"], "commands": [":w"] },
{ "before": ["<leader>", "q"], "commands": [":q"] }
],
"vim.leader": "<space>"
}
19.2 IntelliJ / JetBrains IDE Vim 插件
安装 IdeaVim 插件:
- 支持 Normal/Insert/Visual 模式
- 支持大部分 Vim 命令
- 配置文件:
~/.ideavimrc(格式同.vimrc)
19.3 Bash / Zsh Readline Vim 模式
在 ~/.bashrc 或 ~/.zshrc 中添加:
# Bash
set -o vi
# Zsh
bindkey -v
启用后,命令行的编辑模式变为 Vim 风格:
- 默认是 Insert 模式
Esc进入 Normal 模式- 支持
h/j/k/l、w/b/e、dd/yy/p、/搜索历史等
19.4 tmux
tmux 的 copy mode 支持 Vim 快捷键:
# ~/.tmux.conf
setw -g mode-keys vi
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'y' send -X copy-selection
19.5 其他支持 Vim 模式的工具
| 工具 | 说明 |
|---|---|
| Less / Man | 按 h 查看帮助,支持 j/k/G/g 等 |
| MySQL CLI | 支持 Vim 模式编辑 |
| IPython / Jupyter | %config TerminalInteractiveShell.editing_mode = 'vi' |
| Python REPL | 安装 gnureadline 并设置 set -o vi |
| JupyterLab | 安装 jupyterlab-vim 扩展 |
| Obsidian | Vim 编辑器插件 |
| Notion | 不原生支持,但有社区脚本 |
| 浏览器 | Vimium(Chrome)、Tridactyl(Firefox)、Vimari(Safari) |
| Gmail | 键盘快捷键(部分 Vim 风格) |
| Slack | Vim 风格快捷键(设置中开启) |
19.6 浏览器 Vim 插件示例(Vimium)
安装 Vimium 后,可以用 Vim 风格快捷键浏览网页:
| 快捷键 | 功能 |
|---|---|
h/j/k/l |
滚动 |
gg |
页面顶部 |
G |
页面底部 |
/ |
页面内搜索 |
f |
显示链接字母提示,按字母打开链接 |
r |
刷新 |
x |
关闭 Tab |
t |
新建 Tab |
J/K |
切换 Tab |
20. 高级技巧与工作流
20.1 . 命令(重复上次修改)
. 是 Vim 中最强大的命令之一——它重复你上一次的修改操作。
操作序列 . 的效果
dw 删除下一个单词
x 删除下一个字符
>> 缩进下一行
ci( 修改下一个括号内容
A;text<Esc> 在行尾追加 ;text
应用场景:需要修改多个类似的单词时:
cw修改第一个单词j.在下一行重复修改j.继续...
20.2 Ctrl-n / Ctrl-p 自动补全
在 Insert 模式下:
| 按键 | 功能 |
|---|---|
Ctrl-n |
向下搜索补全(当前 buffer 中的词) |
Ctrl-p |
向上搜索补全 |
Ctrl-x Ctrl-n |
补全当前 buffer 中的关键字 |
Ctrl-x Ctrl-i |
补全包含文件中的关键字 |
Ctrl-x Ctrl-] |
补全标签(需要 ctags) |
Ctrl-x Ctrl-k |
补全字典(需要 set dictionary) |
Ctrl-x Ctrl-l |
补全整行 |
Ctrl-x Ctrl-f |
补全文件名 |
Ctrl-x Ctrl-o |
全能补全(omni completion,语言相关) |
Ctrl-x Ctrl-u |
用户自定义补全 |
Ctrl-x Ctrl-v |
Vim 命令行补全 |
Ctrl-x Ctrl-s |
拼写建议 |
20.3 = 自动缩进
| 命令 | 含义 |
|---|---|
== |
自动缩进当前行 |
=ap |
自动缩进当前段落 |
gg=G |
自动缩进整个文件 |
=i{ |
自动缩进花括号内 |
:%normal == |
所有行自动缩进 |
20.4 g 系列命令
| 命令 | 含义 |
|---|---|
g~{motion} |
翻转大小写 |
gu{motion} |
转小写 |
gU{motion} |
转大写 |
gJ |
合并行(不加空格) |
gq{motion} |
格式化文本(自动换行) |
gw{motion} |
格式化文本(不移动光标) |
gQQ |
格式化模式 |
gg |
到文件首行 |
G |
到文件末行 |
gd |
跳转到本地定义 |
gD |
跳转到全局定义 |
gi |
回到上次 Insert 位置 |
gv |
重选上次 Visual 区域 |
gP |
粘贴在前面(光标在开头) |
gp |
粘贴在后面(光标在末尾) |
g. |
跳转到上次修改位置 |
g, |
向前浏览 changelist |
g; |
向后浏览 changelist |
g& |
在所有行重复上次替换 |
g_ctrl-g |
显示详细字数统计 |
gH |
Select 模式 |
g_CTRL-a |
(Insert模式)数字加 1 |
g_CTRL-x |
(Insert模式)数字减 1 |
20.5 Quickfix 列表
Quickfix 是 Vim 的错误/搜索结果列表。
| 命令 | 含义 |
|---|---|
:make |
运行 make,结果进入 quickfix |
:copen |
打开 quickfix 窗口 |
:cclose |
关闭 quickfix 窗口 |
:cn 或 :cnext |
下一条错误 |
:cp 或 :cprev |
上一条错误 |
:cfirst |
第一条 |
:clast |
最后一条 |
:cnf |
下一个文件的第一条 |
:cpf |
上一个文件的第一条 |
:cc N |
跳到第 N 条 |
:grep pattern *.py |
搜索并将结果放入 quickfix |
:vimgrep /pattern/ **/*.py |
Vim 内置 grep |
:cdo cmd |
对每条 quickfix 条目执行命令 |
:cfdo cmd |
对每个文件执行命令 |
示例工作流:
:vimgrep /TODO/ **/*.py " 搜索所有 TODO
:copen " 打开结果列表
" 在结果中用 Enter 跳转
:cn " 下一条
:cp " 上一条
20.6 Location 列表
Location 列表类似于 Quickfix,但是每个窗口有自己的 Location 列表。
| 命令 | 含义 |
|---|---|
:lopen |
打开 location 窗口 |
:lclose |
关闭 |
:lnext |
下一条 |
:lprev |
上一条 |
:lvimgrep /pattern/ files |
搜索到 location 列表 |
20.7 拼写检查
:set spell " 开启拼写检查
:set spelllang=en " 设置语言(可以多种:en,fr,es)
:set nospell " 关闭
| 命令 | 含义 |
|---|---|
]s |
下一个拼写错误 |
[s |
上一个拼写错误 |
z= |
显示修正建议 |
zg |
将当前词加入好词列表(good) |
zw |
将当前词加入坏词列表(wrong) |
zug |
撤销 zg |
1z= |
直接使用第一个建议 |
20.8 折叠(Folding)
| 命令 | 含义 |
|---|---|
zc |
关闭当前折叠(close) |
zo |
打开当前折叠(open) |
za |
切换折叠状态(toggle) |
zC |
关闭所有嵌套折叠 |
zO |
打开所有嵌套折叠 |
zA |
切换所有嵌套折叠 |
zr |
减少折叠层级(全部打开一级) |
zR |
打开所有折叠 |
zm |
增加折叠层级(全部关闭一级) |
zM |
关闭所有折叠 |
zj |
下一个折叠 |
zk |
上一个折叠 |
[z |
当前折叠开头 |
]z |
当前折叠结尾 |
zd |
删除当前折叠 |
折叠方法:
:set foldmethod=manual " 手动折叠(zf{motion})
:set foldmethod=indent " 按缩进折叠
:set foldmethod=expr " 按表达式折叠
:set foldmethod=syntax " 按语法折叠
:set foldmethod=marker " 按标记折叠({{{ }}})
20.9 Diff 模式
vimdiff file1 file2 " 比较两个文件
vim -d file1 file2 " 同上
| 命令 | 含义 |
|---|---|
]c |
下一个差异 |
[c |
上一个差异 |
do |
从另一窗口获取(diff obtain) |
dp |
推送到另一窗口(diff put) |
:diffupdate |
刷新差异 |
应用场景:Git 合并冲突解决时非常有用。
20.10 会话(Session)
:mksession! mysession.vim " 保存当前会话(窗口布局、buffer 等)
:source mysession.vim " 恢复会话
vim -S mysession.vim " 启动时恢复会话
应用场景:项目开发时保存窗口布局,下次打开快速恢复。
20.11 标签文件(Tags / ctags)
# 生成标签文件
ctags -R .
# 在 Vim 中使用
vim -t function_name " 启动时跳转到函数定义
| 命令 | 含义 |
|---|---|
Ctrl-] |
跳转到光标下标签的定义 |
Ctrl-t |
从标签跳转返回 |
:tag name |
跳转到 name 的定义 |
:tn |
下一个匹配的标签 |
:tp |
上一个匹配 |
:ts name |
列出所有匹配选择 |
:tags |
查看标签栈 |
21. 实战场景合集
场景一:日常代码编辑工作流
目标:高效编辑一个 Python 项目
" 1. 打开项目
vim main.py
" 2. 分屏打开相关文件
:vsplit utils.py " 右侧打开 utils.py
:split test_main.py " 下方打开测试文件
" 3. 在窗口间切换
Ctrl-w h/j/k/l
" 4. 快速跳转函数定义
:tag my_function " 需要 ctags
" 5. 搜索项目中的关键词(需要 fzf 插件)
:Rg import
" 6. 修改函数参数
ci( " 修改括号内参数
" 7. 注释一段代码
V5j " 选中 6 行
gc " 注释/取消注释
" 8. 格式化代码
= " 可视模式下自动缩进
" 9. 保存所有
:wa
场景二:批量编辑 CSV / 日志文件
目标:处理一个 CSV 文件,只保留特定列
name,age,city,country
Alice,25,New York,USA
Bob,30,London,UK
Carol,28,Tokyo,Japan
" 只保留 name 和 city 列:
" 1. 用外部命令 awk 处理
:%!awk -F, '{print $1","$3}'
" 结果:
" name,city
" Alice,New York
" Bob,London
" Carol,Tokyo
" 或者只保留年龄大于 26 的行
:%!awk -F, 'NR==1 || $2>26'
场景三:多行批量注释 / 取消注释
def old_function():
result = compute()
log_result(result)
notify(result)
return result
方法一:可视块模式
" 注释:
1. Ctrl-v 选中要注释的行的行首
2. Shift-i (I) 输入 #
3. Esc
" 取消注释:
1. Ctrl-v 选中 # 所在列
2. d
方法二:vim-commentary 插件
gcc " 注释/取消注释当前行
gcip " 注释整个段落
V5j gc " 注释选中的 6 行
方法三:命令行
:5,8s/^/#/ " 第 5-8 行加注释
:5,8s/^#// " 第 5-8 行去注释
场景四:代码格式化与对齐
目标:将变量赋值语句对齐
name = "Alice"
age = 25
city = "NYC"
country = "USA"
方法一:vim-easy-align 插件
" 选中所有行,按 = 对齐
vip
:EasyAlign =
结果:
name = "Alice"
age = 25
city = "NYC"
country = "USA"
方法二:tabular 插件
:Tabularize /=
方法三:外部 column 命令
:%!column -t -s=
场景五:在多个文件中搜索替换
目标:将所有 .py 文件中的 old_name 替换为 new_name
" 方法一:用 vimgrep + cdo
:vimgrep /old_name/ **/*.py
:cdo s/old_name/new_name/g | update
" 方法二:用外部命令(更快)
" 退出 Vim 后用 sed
" sed -i 's/old_name/new_name/g' *.py
" 方法三:在 Vim 中用 arg
:args **/*.py
:argdo %s/old_name/new_name/g | update
场景六:编辑远程文件
" 方法一:直接用 scp 路径(需要 netrw 插件,Vim 自带)
:e scp://user@server//path/to/file
:e scp://user@server/~/relative/path
" 方法二:用 sshfs 挂载后编辑
" sshfs user@server:/path /mnt/remote
" vim /mnt/remote/file
" 方法三:通过 ssh + vim
ssh user@server -t vim /path/to/file
场景七:Git 合并冲突解决
<<<<<<< HEAD
这是当前分支的代码
=======
这是另一分支的代码
>>>>>>> feature-branch
" 方法一:手动解决
/<<<<<<< " 搜索冲突标记
dd " 删除 <<<<<<< 行
/=======
V/>>>>>>>
" 选中到 >>>>>>> 部分删除,保留需要的代码
" 方法二:使用 vim-fugitive
:Gdiff " 打开三路 diff
" 在 working copy 中用 do/dp 选择保留哪个版本
:Gwrite " 标记为已解决
" 方法三:用 :g 命令快速删除所有冲突标记行
:g/^<<<<<<<\|^=======\|^>>>>>>>/d
" ⚠️ 注意:这会删除标记行,但你需要手动合并代码
场景八:Markdown 写作工作流
" 推荐的 Markdown 写作配置
augroup markdown_writing
autocmd!
autocmd FileType markdown setlocal wrap
autocmd FileType markdown setlocal spell
autocmd FileType markdown setlocal textwidth=80
autocmd FileType markdown setlocal concealcursor=n
augroup END
" 快捷键映射(仅 Markdown)
autocmd FileType markdown nnoremap <buffer> <leader>1 m`I# <Esc>```
autocmd FileType markdown nnoremap <buffer> <leader>2 m`I## <Esc>```
autocmd FileType markdown nnoremap <buffer> <leader>3 m`I### <Esc>```
autocmd FileType markdown nnoremap <buffer> <leader>b m`i**<Esc>``i*<Esc>lviwU
autocmd FileType markdown nnoremap <buffer> <leader>i m`i*<Esc>
autocmd FileType markdown nnoremap <buffer> <leader>c m`I- [ ] <Esc>
" 格式化表格
" 选中表格行后:
:'<,'>!column -t -s '|'
" 预览(需要插件或外部工具)
" 安装 markdown-preview.nvim 插件
场景九:处理大文件
" 打开大文件前禁用某些功能(提升性能)
" 在 .vimrc 中添加:
autocmd BufReadPre *.log let b:large_file = 1
autocmd BufReadPre *.log setlocal noswapfile nowrap norelativenumber
" 或者手动操作大文件:
: set nowrap " 关闭自动换行
: set noswapfile " 关闭交换文件
: syntax off " 关闭语法高亮
: set foldmethod=manual " 手动折叠
" 跳转到特定行
:100000 " 跳到第 10 万行
G " 文件末尾
gg " 文件开头
" 只查看文件
vim -R huge.log " 只读模式
vim -u NONE -R huge.log " 不加载任何配置,最快
" 用外部命令处理
:%!grep ERROR " 只保留 ERROR 行
:%!tail -1000 " 只保留最后 1000 行
:%!head -1000 " 只保留前 1000 行
场景十:调试与 Quickfix 工作流
" 1. 设置 makeprg(如果不用 make)
:set makeprg=python3\ %
" 或
:set makeprg=npm\ run\ build
" 2. 运行 :make
:make
" 3. 打开 quickfix 窗口查看错误
:copen
" 4. 在错误间跳转
:cn " 下一个错误
:cp " 上一个错误
:cc 3 " 跳到第 3 个错误
" 5. 修复错误后重新运行
:make
22. 故障排查与常见问题
22.1 常见问题
Q: 退出 Vim?
:q " 退出
:q! " 强制退出(不保存)
:wq " 保存退出
ZZ " 保存退出(Normal 模式)
ZQ " 不保存退出(Normal 模式)
Q: 如何关闭搜索高亮?
:nohlsearch " 或 :noh
" 永久关闭:set nohlsearch
Q: 粘贴时代码缩进混乱?
" 方法一:使用粘贴模式
:set paste " 进入粘贴模式
" 粘贴内容
:set nopaste " 退出粘贴模式
" 方法二(推荐):配置 clipboard
:set clipboard=unnamedplus " Linux
:set clipboard=unnamed " macOS
" 方法三:用寄存器
"+p " 从系统剪贴板粘贴
Q: 中文字符显示乱码?
:set encoding=UTF-8
:set fileencoding=UTF-8
:set fileencodings=ucs-bom,UTF-8,GBK,GB18030,big5,euc-jp,euc-kr,latin1
Q: 如何恢复崩溃前的文件?
" Vim 崩溃后,交换文件 .file.swp 存在
vim file.original
" Vim 会提示:
" Swap file ".file.swp" already exists!
" [O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete, (Q)uit, (A)bort:
" 选择 R 恢复
" 恢复后保存,然后删除交换文件
:w
:!rm .file.swp
Q: Backspace 或方向键不正常?
:set backspace=indent,eol,start
" 或在 .vimrc 中
set nocompatible
Q: 如何重复上次 Ex 命令?
:@: " 重复上次的 : 命令
Q: Tab 显示为 4 个空格但按 Tab 键还是插入 Tab?
:set expandtab " Tab 键插入空格
:set tabstop=4 " 已有 Tab 显示为 4 个空格宽
:set shiftwidth=4 " 缩进宽度
" 将已有 Tab 转为空格
:retab
Q: 如何显示隐藏字符?
:set list " 显示隐藏字符
:set nolist " 关闭
:set listchars=tab:▸\ ,trail:·,eol:¬,space:.
Q: 如何切换大小写?
~ " 翻转当前字符大小写
g~~ " 翻转当前行
guu " 当前行转小写
gUU " 当前行转大写
guw " 当前单词转小写
gUw " 当前单词转大写
Q: 如何在多行行首插入相同文本?
" 方法一:可视块
Ctrl-v " 选中行
I " 在行首插入
text " 输入文本
Esc " 应用到所有行
" 方法二:命令
:%normal Iprefix_
Q: 系统剪贴板不工作?
" 检查是否支持剪贴板
:echo has('clipboard')
" 如果输出 0,需要安装 vim-gtk 或 vim-x11
" Ubuntu/Debian
" sudo apt install vim-gtk
" macOS
" set clipboard=unnamed
Q: 如何记住这么多命令?
- 不需要一次全记住
- 从最常用的开始:
h j k l i w q :w :q - 每天学一个新命令
- 用
:help查阅 - 打印速查表贴在显示器旁
23. 常用速查表
23.1 初学者必备 20 命令
| 命令 | 功能 |
|---|---|
i |
进入插入模式 |
Esc |
回到普通模式 |
:w |
保存 |
:q |
退出 |
:wq |
保存并退出 |
:q! |
不保存退出 |
h j k l |
左 下 上 右 |
w b |
下一个/上一个单词 |
gg G |
文件开头/末尾 |
dd |
删除整行 |
yy |
复制整行 |
p |
粘贴 |
u |
撤销 |
Ctrl-r |
重做 |
/word |
搜索 word |
n N |
下一个/上一个搜索结果 |
x |
删除字符 |
o |
下方新行 |
a |
光标后插入 |
:help |
帮助 |
23.2 进阶常用 50 命令
| 命令 | 功能 |
|---|---|
ciw |
修改当前单词 |
ci( |
修改括号内 |
ci" |
修改引号内 |
da( |
删除括号(含括号) |
dt) |
删除到 ) 前 |
df) |
删除到 ) (含)) |
. |
重复上次修改 |
* |
搜索光标下的词 |
:%s/old/new/g |
全文替换 |
:noh |
取消搜索高亮 |
V |
行选择 |
Ctrl-v |
块选择 |
> / < |
缩进/反缩进 |
=ap |
格式化段落 |
gg=G |
格式化整个文件 |
ctrl-o / ctrl-i |
跳回/跳前 |
f( ; |
行内查找括号 |
0 ^ $ |
行首/非空行首/行尾 |
H M L |
屏幕顶/中/底 |
zz |
当前行居中 |
Ctrl-d / Ctrl-u |
半屏翻页 |
ma \a` |
设标记 a / 跳到 a |
qa ... q |
录制宏 a |
@a |
执行宏 a |
@@ |
重复上次宏 |
"ayy "ap |
复制到寄存器 a / 粘贴 |
"+yy "+p |
系统剪贴板复制/粘贴 |
:e file |
打开文件 |
:ls :bn :bp |
buffer 列表/下一个/上一个 |
:sp :vs |
分屏 |
Ctrl-w h/j/k/l |
窗口切换 |
:tabnew gt gT |
新 Tab/下一个/上一个 |
:g/pattern/d |
删除匹配行 |
:v/pattern/d |
删除不匹配行 |
r R |
替换字符/替换模式 |
~ gUU guu |
大小写翻转/全大写/全小写 |
J |
合并行 |
>> << |
缩进/反缩进 |
m{A-Z} \` |
全局标记 |
Ctrl-] Ctrl-t |
标签跳转/返回 |
:sort |
排序 |
:!cmd |
执行 shell 命令 |
:r !cmd |
插入命令输出 |
:%!cmd |
过滤整个文件 |
:set paste |
粘贴模式 |
:set nu rnu |
行号/相对行号 |
set et ts=4 sw=4 |
Tab 设为 4 空格 |
gd |
跳转到定义 |
gi |
回到上次编辑位置 |
gv |
重选上次选择 |
23.3 移动命令速查
┌─ ↑ k ─┐ ┌─── K (5k) ───┐
← h ─┤ ├─ l → │ │
└─ ↓ j ─┘ └─── J (5j) ───┘
0 ^ $ 词级 文件级
├─┤├──┤ w W e E B gg ──→ 文件首
行首 非空 行尾 b b e e b G ──→ 文件末
:42→ 第42行
屏幕级 查找 跳转
H ──→ 顶 f/F/t/T Ctrl-o ←── 上一个位置
M ──→ 中 ; / , Ctrl-i →── 下一个位置
L ──→ 底 / ? n N `` ───── 两个位置切换
23.4 文本对象速查
操作符 + i/a + 对象
┌────── 操作符 ──────┐
│ d c y v > < = ~ r │
└───────────────────┘
↓
┌── i / a ──┐
│ i = 内 │
│ a = 含环绕 │
└───────────┘
↓
┌──── 对象 ────┐
│ w W s p t │
│ ( [ { < ' │
│ " ` , . ; : │
└──────────────┘
常用组合:
ciw ci( ci" ci{ cit
diw di( di" di{ dit
yi( yi" yi{
23.5 模式切换速查
Normal(默认)
│
├── i I a A o O s S gi →→→ Insert
├── v V Ctrl-v →→→ Visual
├── R gR →→→ Replace
├── : / ? →→→ Command-line
└── Esc ←── 从任何模式回到 Normal
23.6 命令行速查
文件操作
:w :q :wq :x :q! ZZ ZQ
外部命令
:!cmd :r !cmd :%!cmd
替换
:s/old/new/ 当前行
:s/old/new/g 当前行全部
:%s/old/new/g 全文
:%s/old/new/gc 确认
:'<,'>s/old/new/g 选中区域
全局命令
:g/pattern/d 删除匹配
:v/pattern/d 删除不匹配
:g/pattern/m$ 移到末尾
:g/pattern/t. 复制到当前行
结语
Vim 的学习曲线确实陡峭,但一旦掌握,它将成为你最强大的编辑工具。关键要点:
- 先学基础:模式切换 + h/j/k/l + 基本编辑命令
- 每日练习:每天学一个新命令,比一次性学完更有效
- 使用
.vimrc:逐步定制你的编辑环境 - 少用鼠标:强迫自己用键盘完成所有操作
- 用
:help:Vim 的内置帮助文档是最权威的参考
"Vim 不是学完的,是练出来的。"

浙公网安备 33010602011771号