11622 字
58 分钟

Vim 编辑器完全指南:从入门到精通 | 2026 最新实践

你有没有遇到过这些场景:

  • SSH 到服务器改配置文件,vi 打开后一顿乱按,改了半天不知道怎么保存退出
  • 远程调试代码,VS Code Remote 连不上,只能用终端,却连复制粘贴都费劲
  • 看同事在 Vim 里双手翻飞,光标像长了眼睛一样精准跳转,自己却还在 hjkl 一下一下挪

Vim 是 Linux 服务器上唯一保证可用的文本编辑器——和 SSH 一样基础,但大多数人从未真正学会它。

本文从零开始,系统讲解 Vim 的完整知识体系:

  • 四种模式与核心概念
  • 移动、编辑、搜索替换全操作
  • 多文件编辑(缓冲区/窗口/标签页)
  • 可视化模式、寄存器、宏录制
  • 文本对象(ciwda" 等高效操作)
  • 自定义配置 .vimrc(从基础到生产级模板)
  • 插件管理 vim-plug 与推荐插件
  • Neovim 迁移与 Vim + Tmux 工作流
  • 常见问题排查与最佳实践

1. Vim 是什么#

1.1 为什么 2026 年还要学 Vim#

场景为什么需要 Vim
SSH 远程服务器服务器上没有 GUI,Vim 是唯一保证可用的编辑器
快速编辑配置文件vim nginx.conf 比 VS Code Remote 快 10 倍
Git commit默认编辑器是 Vim,不会用连 commit 都提交不了
提升编辑效率熟练后双手不离键盘,操作速度远超鼠标
快捷键通用VS Code / IntelliJ / Chrome 都有 Vim 插件

1.2 Vim vs Neovim vs VS Code#

特性VimNeovimVS Code
出现年份199120142015
配置语言Vim ScriptLua + Vim ScriptJSON
内嵌终端
LSP 原生支持
异步任务Vim 8+✅ 原生
插件生态成熟但趋缓活跃增长最活跃
启动速度极快(<50ms)极快(<50ms)较慢(1-3s)
服务器可用✅ 默认安装需手动安装❌ 需 Remote
学习曲线陡峭陡峭(与 Vim 一致)平缓
适合场景服务器编辑/快速修改日常开发/服务器日常开发

选择建议:

  • 服务器运维 → Vim(默认安装,零配置可用)
  • 终端开发 → Neovim(Lua 配置 + LSP + Treesitter)
  • 图形界面开发 → VS Code + Vim 插件(兼顾效率和图形化)

1.3 Vim 的设计哲学#

Vim 的核心设计理念是 「编辑器的速度应与思维速度匹配」

  1. 模式编辑 — 不同模式做不同的事,按键含义随模式变化
  2. 双手不离键盘 — 所有操作通过键盘完成,鼠标是效率瓶颈
  3. 语法化命令 — 命令有语法结构(动词 + 名词),可组合
  4. 可重复. 重复上次操作,高效操作的基石

核心理解:Vim 不是”难用的编辑器”,而是”需要学习的编辑器”。一旦度过初始学习曲线,效率会指数级提升。


2. 安装#

2.1 各平台安装#

Terminal window
# Ubuntu / Debian
sudo apt update && sudo apt install vim
# CentOS / RHEL / Fedora
sudo dnf install vim-enhanced # Fedora / RHEL 8+
sudo yum install vim-enhanced # CentOS 7
# macOS(系统自带的是精简版,建议安装完整版)
brew install vim
# Arch Linux
sudo pacman -S vim
# Windows
# 方法1: 使用 winget
winget install vim.vim
# 方法2: 使用 scoop
scoop install vim
# 方法3: 使用 choco
choco install vim

2.2 验证安装#

Terminal window
vim --version

输出中关注以下信息:

VIM - Vi IMproved 9.1 (2024 Jan 02)
Compiled Mar 15 2026 00:00:00
Normal version without GUI.
+acl +file_in_path +mouse_sgr +tag_binary
+arabic +find_in_path -mouse_sysmouse -tag_any_white
+autocmd +float +mouse_urxvt -tcl
...
  • + 表示已启用该功能
  • - 表示未编译该功能
  • 确保有 +clipboard(系统剪贴板支持)和 +python3(插件依赖)

如果没有 +clipboard:在 Linux 上安装 vim-gtkvim-gtk3;macOS 上用 brew install vim

2.3 Neovim 安装#

Terminal window
# Ubuntu / Debian
sudo apt install neovim
# macOS
brew install neovim
# Fedora / RHEL 8+
sudo dnf install neovim
# Arch Linux
sudo pacman -S neovim
# Windows
winget install Neovim.Neovim

3. 四种模式#

模式是 Vim 最核心的概念。理解模式,就理解了 Vim 的一切。

3.1 模式总览#

┌─────────────────────────────────────────────────────┐
│ Vim 模式系统 │
├─────────────┬───────────────────────────────────────┤
│ 普通模式 │ 默认模式,所有按键都是命令 │
│ (Normal) │ 按 Esc 进入 │
├─────────────┼───────────────────────────────────────┤
│ 插入模式 │ 输入文本,和普通编辑器一样 │
│ (Insert) │ 按 i/a/o 等从普通模式进入 │
├─────────────┼───────────────────────────────────────┤
│ 可视模式 │ 选中文本(字符/行/块) │
│ (Visual) │ 按 v/V/Ctrl+v 从普通模式进入 │
├─────────────┼───────────────────────────────────────┤
│ 命令模式 │ 输入 Ex 命令(保存/退出/替换等) │
│ (Command) │ 按 : 从普通模式进入 │
└─────────────┴───────────────────────────────────────┘

3.2 普通模式(Normal Mode)#

默认模式,也是停留时间最长的模式。 在这个模式下,按键不是输入文字,而是执行命令。

" 以下按键在普通模式下执行:
h " 左移光标
j " 下移光标
k " 上移光标
l " 右移光标
x " 删除光标处字符
dd " 删除整行
yy " 复制整行
p " 粘贴
u " 撤销
Ctrl+r " 重做

黄金法则:不确定自己在什么模式?按 Esc 回到普通模式。

3.3 插入模式(Insert Mode)#

从普通模式进入插入模式的多种方式:

按键含义光标位置
iinsert在光标前插入
aappend在光标后插入
I大写 I在行首插入
A大写 A在行末插入
oopen在下方新开一行
O大写 O在上方新开一行
ssubstitute删除光标字符并进入插入
S大写 S删除整行并进入插入
cwchange word删除当前单词并进入插入
ccchange line删除整行并进入插入
" 实战:快速在行末添加分号
A; " 在行末插入分号,然后 Esc 回普通模式
" 实战:在当前行下方新开一行写注释
o# TODO: " 下方新行并输入注释

记忆技巧i = insert(前),a = append(后),o = open(新行)。大写 = 行首/行末版本。

3.4 可视模式(Visual Mode)#

选中文本后可以执行操作(复制、删除、替换等):

按键模式选择方式
v字符可视按字符选择
V行可视按整行选择
Ctrl+v块可视按矩形块选择(列编辑)
" 实战:选中并复制一段文字
v " 进入字符可视模式
jjjj " 向下移动选中多行
y " 复制选中文本
" 实战:批量缩进
V " 进入行可视模式
jj " 向下选中 3 行
> " 向右缩进(一次缩进 shiftwidth)
" 实战:块编辑——给多行行首添加注释
Ctrl+v " 进入块可视模式
jjj " 向下选中 4 行
I " 在块开头插入(大写 I)
# " 输入注释符
Esc " 按 Esc,所有选中行都会添加 #

块可视模式 是 Vim 的杀手锏——在 VS Code 中需要安装插件才能实现的列编辑,Vim 原生支持。

3.5 命令模式(Command-Line Mode)#

在普通模式下按 : 进入,用于执行 Ex 命令:

:w " 保存
:q " 退出
:wq " 保存并退出
:q! " 强制退出(不保存)
:x " 保存并退出(等同 :wq,但仅在有修改时才写盘)
:wqa " 保存所有并退出
:w filename " 另存为
:r filename " 读入另一个文件内容插入到光标处
:set number " 显示行号
:set paste " 进入粘贴模式(避免自动缩进混乱)
:e file.txt " 打开另一个文件
:!ls " 执行外部 Shell 命令
:%!sort " 对全文执行外部 sort 命令

3.6 模式切换速查图#

┌──────────┐
│ 普通模式 │ ◄──── 默认模式
│ Normal │
└────┬─────┘
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ 插入 │ │ 可视 │ │ 命令 │
│Insert │ │Visual │ │Command│
└───┬───┘ └───┬───┘ └───┬───┘
│ │ │
└─────────┼─────────┘
按 Esc
回到普通模式

核心习惯:完成一个操作后立即按 Esc 回到普通模式。普通模式是你的”家”。


4. 移动与跳转#

Vim 的移动命令极其丰富,这是高效编辑的基础。

4.1 基本移动#

h " 左
j " 下
k " 上
l " 右

新手提示:刚入门时用方向键也完全可以,但建议尽快过渡到 hjkl——手不离主键区是效率的关键。

4.2 按单词移动#

按键含义示例
w下一个单词开头hello-world → w 跳到 -
W下一个 WORD 开头(以空格分隔)hello-world → W 跳到下个词
b上一个单词开头backward
B上一个 WORD 开头
e当前/下一个单词末尾end
E当前/下一个 WORD 末尾
ge上一个单词末尾

word vs WORD:小写命令以”标点符号”为分词边界(hello-world 是 3 个 word),大写命令仅以”空格”为边界(hello-world 是 1 个 WORD)。

4.3 行内跳转#

按键跳转到
0行首
^第一个非空字符
$行末
g_最后一个非空字符
f{x}当前行下一个字符 x(find)
F{x}当前行上一个字符 x
t{x}当前行下一个字符 x 前面(till)
T{x}当前行上一个字符 x 后面
;重复上次 f/F/t/T
,反向重复上次 f/F/t/T
" 实战:快速跳到行末的分号
f; " 在当前行找下一个 ;
" 实战:修改括号内的内容
f( " 跳到 (
ci) " change inside ) — 删除括号内容并进入插入模式

4.4 文件内跳转#

按键跳转到
gg文件第一行
G文件最后一行
{n}G第 n 行(如 42G 跳到第 42 行)
{n}gg第 n 行(同上)
:{n}第 n 行(命令模式)
H屏幕顶部(High)
M屏幕中部(Middle)
L屏幕底部(Low)
Ctrl+d向下翻半页
Ctrl+u向上翻半页
Ctrl+f向下翻整页
Ctrl+b向上翻整页
%跳到匹配的括号 () [] {}
*向下搜索光标下的单词
#向上搜索光标下的单词
" 实战:快速跳到函数定义
gg " 先到文件头
/function " 搜索 function
Enter " 跳到匹配处
" 实战:在括号间跳转
% " 光标在 ( 上,按 % 跳到匹配的 )

4.5 标记(Mark)#

标记可以让你在文件内设置”书签”,快速跳回:

按键含义
m{a-z}设置标记 a-z(当前文件内)
m{A-Z}设置全局标记 A-Z(跨文件)
`{a-z}跳到标记的行和列
'{a-z}跳到标记的行首
跳回上次跳转前的位置
`"跳到上次退出文件时的位置
`.`跳到上次修改的位置
" 实战:在文件内设置书签
ma " 在当前位置设置标记 a
' 翻到文件底部做些操作
`a " 跳回标记 a 的精确位置

5. 编辑操作#

5.1 删除#

按键含义
x删除光标处字符
X删除光标前字符
dd删除整行
dw删除到下一个单词开头
de删除到当前单词末尾
d$删除到行末
d0删除到行首
dG删除到文件末尾
dgg删除到文件开头
d{motion}删除到 {motion} 指定的位置
D删除到行末(等同 d$
J合并下一行到当前行(删除换行符)
" 实战:删除一个单词
daw " delete around word — 删除整个单词(含周围空格)
diw " delete in word — 删除单词(不含空格)
" 实战:删除到某个字符
dt; " 删除直到分号前
df; " 删除直到分号(含分号)

5.2 复制与粘贴#

按键含义
yy复制整行(yank)
yw复制一个单词
y$复制到行末
y{motion}复制到 motion 指定的位置
p在光标后粘贴
P在光标前粘贴
gp粘贴并将光标移到粘贴文本末尾
dd + p剪切粘贴(dd 会将内容放入寄存器)
" 实战:复制当前行到文件末尾
yy " 复制当前行
G " 跳到文件末尾
p " 粘贴
" 实战:复制 3 行
3yy " 复制 3 行

5.3 撤销与重做#

按键含义
u撤销(undo)
Ctrl+r重做(redo)
U撤销整行所有修改
Ctrl+r重做被撤销的操作
" 实战:撤销多次操作
uuu " 撤销 3 次
Ctrl+r " 重做 1 次

Vim 9+ 的 undo 树:Vim 的撤销不是线性的,而是一棵树。用 :undolist 查看撤销分支,:earlier 10m 回到 10 分钟前的状态。

5.4 替换#

按键含义
r{x}替换光标字符为 x(不进入插入模式)
R进入替换模式(覆盖写入)
c{motion}删除并进入插入模式(change)
C删除到行末并进入插入模式(等同 c$
cw删除当前单词并进入插入
cc删除整行并进入插入
~切换大小写
g~{motion}切换 motion 范围的大小写
gU{motion}转大写
gu{motion}转小写
" 实战:将当前单词转为大写
gUiw " 当前单词转大写
" 实战:修改字符串内容
ci" " change inside " — 删除引号内内容并插入
" 实战:替换单个字符
r1 " 将当前字符替换为 1

5.5 缩进#

按键含义
>>当前行右缩进
<<当前行左缩进
>{motion}motion 范围右缩进
<{motion}motion 范围左缩进
=自动缩进当前行
gg=G全文自动缩进
=i{自动缩进当前花括号块
" 实战:全文格式化
gg=G " 跳到文件头,自动缩进到文件末尾
" 实战:缩进 5 行
5>> " 当前行及下面 4 行右缩进

6. 搜索与替换#

6.1 搜索#

/keyword " 向下搜索 keyword
?keyword " 向上搜索 keyword
n " 跳到下一个匹配
N " 跳到上一个匹配
* " 向下搜索光标下的单词
# " 向上搜索光标下的单词
g* " 向下搜索光标下的单词(部分匹配)
g# " 向上搜索光标下的单词(部分匹配)

搜索选项设置:

:set ignorecase " 忽略大小写
:set smartcase " 智能大小写(有小写时忽略大小写,有大写时精确匹配)
:set hlsearch " 高亮搜索结果
:set incsearch " 实时增量搜索(输入时即跳转)

搜索正则表达式:

/^function " 搜索行首的 function
/function$ " 搜索行末的 function
/\<word\> " 精确匹配单词 word(不匹配 keyword)
/\d\+ " 搜索数字(Vim 正则中 + 需转义为 \+)
/\v\d+ " 使用 \v 魔术模式,+ 不用转义
/\ckeyword " 忽略大小写搜索(单次)
/\Ckeyword " 区分大小写搜索(单次)

正则技巧:Vim 默认正则语法较特殊(+ 需写成 \+),在模式前加 \v 可切换为”魔术模式”,此时 +()| 等不需要转义,更接近 PCRE 语法。

6.2 替换#

替换命令格式:

:[range]s/pattern/replacement/[flags]

范围(range):

范围含义
%全文
n第 n 行
n,m第 n 到 m 行
.当前行
$最后一行
'<,'>可视模式选中的范围

标志(flags):

标志含义
g替换行内所有匹配(默认只替换第一个)
i忽略大小写
c每次替换前确认
e没有匹配时不报错
n只统计匹配数,不实际替换
" 基础替换
:s/old/new/ " 当前行第一个 old 替换为 new
:s/old/new/g " 当前行所有 old 替换为 new
:%s/old/new/g " 全文替换
:%s/old/new/gc " 全文替换,逐个确认
:%s/old/new/gi " 全文替换,忽略大小写
" 指定范围替换
:5,20s/old/new/g " 第 5-20 行替换
:'<,'>s/old/new/g " 可视模式选中范围替换(在可视模式选中后按 :)
" 捕获组替换
:%s/\v(\w+)@(\w+)/\2@\1/g " 交换 email 的用户名和域名
" 删除行首空格
:%s/^\s\+//g
" 删除行尾空格
:%s/\s\+$//g
" 统计匹配数
:%s/old//gn " 统计全文 old 出现次数
" 在每行行首添加
:%s/^/# / " 全文添加注释
:5,10s/^/# / " 第 5-10 行添加注释

确认替换交互:

replace with new (y/n/a/q/l/^E/^Y)?
按键含义
yyes,替换
nno,不替换
aall,替换剩余所有
qquit,退出替换
llast,替换后退出
Ctrl+e向下滚动一行
Ctrl+y向上滚动一行

6.3 实用搜索替换场景#

" 将 Tab 替换为 4 个空格
:%s/\t/ /g
" 将连续空行压缩为单个空行
:%s/\n\{3,}/\r\r/g
" 将 Windows 换行符转为 Unix
:%s/\r//g
" 将驼峰命名转为下划线
:%s/\v([a-z])([A-Z])/\1_\2/g
" 提取所有 URL
:%s/\v(https?:\/\/[^\s]+)//gn
" 给 JSON 的 key 加引号
:%s/\v(\w+):/"\1":/g

7. 多文件编辑#

7.1 缓冲区(Buffer)#

缓冲区是 Vim 中打开的文件的内存表示:

:e file.txt " 在新缓冲区打开文件
:ls " 列出所有缓冲区
:bn " 下一个缓冲区(buffer next)
:bp " 上一个缓冲区(buffer previous)
:b{n} " 切换到第 n 个缓冲区
:bf " 第一个缓冲区
:bl " 最后一个缓冲区
:bd " 关闭当前缓冲区(buffer delete)
:b# " 切换到上次访问的缓冲区
:ball " 为所有缓冲区打开窗口

缓冲区状态:

:ls
1 #h "file1.txt" line 1
2 %a "file2.txt" line 15
3 "file3.txt" line 1
标记含义
%当前缓冲区
#交替缓冲区(上次访问的)
aactive(有窗口显示)
hhidden(隐藏,未显示)
+有未保存修改
-不可修改

7.2 窗口(Window)#

窗口是查看缓冲区的视口,一个缓冲区可以在多个窗口中显示:

:split " 水平分屏(或 :sp)
:vsplit " 垂直分屏(或 :vs)
:split file.txt " 水平分屏打开文件
:new " 水平分屏创建空缓冲区
:vnew " 垂直分屏创建空缓冲区

窗口间移动(快捷键):

Ctrl+w h " 移到左边窗口
Ctrl+w j " 移到下边窗口
Ctrl+w k " 移到上边窗口
Ctrl+w l " 移到右边窗口
Ctrl+w w " 在窗口间循环切换
Ctrl+w H " 将当前窗口移到最左
Ctrl+w J " 将当前窗口移到最下
Ctrl+w K " 将当前窗口移到最上
Ctrl+w L " 将当前窗口移到最右
Ctrl+w = " 所有窗口等大
Ctrl+w + " 增大当前窗口高度
Ctrl+w - " 减小当前窗口高度
Ctrl+w > " 增大当前窗口宽度
Ctrl+w < " 减小当前窗口宽度
Ctrl+w _ " 最大化当前窗口高度
Ctrl+w | " 最大化当前窗口宽度
Ctrl+w c " 关闭当前窗口
Ctrl+w o " 关闭其他所有窗口(only)
Ctrl+w r " 窗口位置轮换
Ctrl+w T " 将当前窗口移到新标签页

推荐映射:在 .vimrc 中设置 nnoremap <C-h> <C-w>h 等,可以用 Ctrl+h/j/k/l 直接切换窗口。

" 实战:左侧代码 + 右侧终端日志
:vsplit " 垂直分屏
Ctrl+w l " 移到右侧
:e log.txt " 打开日志文件
Ctrl+w h " 回到左侧写代码

7.3 标签页(Tab)#

Vim 的标签页是窗口布局的集合,不是”一个文件一个标签”:

:tabnew " 新建标签页
:tabnew file.txt " 在新标签页打开文件
:tabclose " 关闭当前标签页
:tabn " 下一个标签页(或 gt)
:tabp " 上一个标签页(或 gT)
:tabfirst " 第一个标签页
:tablast " 最后一个标签页
:{n}gt " 切换到第 n 个标签页
:tabmove " 将标签页移到最后
:tabmove 0 " 将标签页移到最前
:tabs " 列出所有标签页
" 实战:标签页工作流
:tabnew src/main.py " 标签页1:编辑代码
:tabnew src/test.py " 标签页2:编写测试
:tabnew config.yml " 标签页3:配置文件
gt " 在标签页间切换

7.4 三者关系#

┌─────────────────────────────────────────────┐
│ Tab(标签页) │
│ ┌──────────────────────────────────────┐ │
│ │ Window(窗口) │ Window(窗口) │ │
│ │ ┌──────────────┐ │ ┌──────────────┐│ │
│ │ │ Buffer │ │ │ Buffer ││ │
│ │ │ (file.txt) │ │ │ (log.txt) ││ │
│ │ └──────────────┘ │ └──────────────┘│ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
- Buffer = 文件在内存中的表示(一个文件 = 一个 Buffer)
- Window = 查看 Buffer 的视口(可以分割多个)
- Tab = 窗口布局的集合(一个 Tab 可以包含多个 Window)

核心理解:Vim 的 Tab 更像是”工作区”而非浏览器标签。一个 Tab 内可以有多个窗口,每个窗口显示一个 Buffer。


8. 文本对象#

文本对象是 Vim 最强大的特性之一——它让你用”语义”而非”字符”来操作文本。

8.1 文本对象语法#

{operator}{a|i}{object}
  • operatord(删除)、c(修改)、y(复制)、v(选中)
  • a/ia = around(含周围分隔符),i = inside(不含分隔符)
  • object:文本对象类型

8.2 常用文本对象#

对象含义示例
wworddaw 删除整个单词
WWORDdaW 删除整个 WORD
ssentencedas 删除整个句子
pparagraphdap 删除整个段落
tXML/HTML 标签dat 删除 <div>...</div>
"双引号内ci" 修改引号内内容
'单引号内ci' 修改单引号内内容
`反引号内ci` 修改反引号内内容
()括号内ci( 修改括号内内容
[]方括号内da[ 删除方括号及内容
{}花括号内ci{ 修改花括号内内容
<>尖括号内ci< 修改尖括号内内容

8.3 实战示例#

" 修改字符串内容
ci" " change inside " — 删除双引号内文本并进入插入
" 删除括号及内容
da( " delete around ( — 删除 (...) 整体
" 复制花括号内代码
yi{ " yank inside { — 复制 { ... } 内的代码
" 修改 HTML 标签内容
cit " change inside tag — 修改 <p>内容</p> 中的"内容"
" 选中整个段落
vap " visual around paragraph
" 修改函数参数
ci( " 光标在括号内,修改参数列表

效率飞跃:学会文本对象后,你不再需要数字符或进入可视模式选中——直接告诉 Vim “修改引号里的内容”即可。

8.4 自定义文本对象#

" 添加下划线文本对象(如 snake_case_variable)
vnoremap au :<C-U>normal! F_vt_<CR>
onoremap au :<C-U>normal! F_vt_<CR>
" 添加逗号分隔文本对象
xnoremap a, :<C-U>normal! F,vt,<CR>
onoremap a, :<C-U>normal! F,vt,<CR>

9. 寄存器#

寄存器是 Vim 的”剪贴板”——Vim 不只有一个剪贴板,而是有多个命名的寄存器。

9.1 寄存器类型#

寄存器名称含义
"无名寄存器默认的复制/删除目标
0数字 0最近复制的文本(仅 yank)
1-9数字 1-9最近删除的文本(1 是最新)
a-z命名寄存器用户手动指定
A-Z大写命名追加到对应小写寄存器
+系统剪贴板与系统剪贴板互通
*主选择区X11 PRIMARY 选区
_黑洞寄存器写入即丢弃(不污染历史)
.只读最近插入的文本
%只读当前文件名
:只读最近执行的命令
/只读最近搜索的模式

9.2 寄存器操作#

" 查看所有寄存器
:reg
" 复制到命名寄存器
"ayy " 将当前行复制到寄存器 a
"byy " 将当前行复制到寄存器 b
" 粘贴命名寄存器
"ap " 粘贴寄存器 a 的内容
"bp " 粘贴寄存器 b 的内容
" 追加到寄存器(大写)
"Ayy " 将当前行追加到寄存器 a
" 使用系统剪贴板
"+yy " 复制当前行到系统剪贴板
"+p " 从系统剪贴板粘贴
" 使用黑洞寄存器(删除但不影响剪贴板)
"_dd " 删除行但不放入任何寄存器
" 使用只读寄存器
"%p " 粘贴当前文件名
":p " 粘贴最近执行的命令

9.3 实战场景#

" 场景1:复制多个片段到不同寄存器
"ayy " 复制第 1 段到寄存器 a
"byy " 复制第 2 段到寄存器 b
"ap " 粘贴第 1 段
"bp " 粘贴第 2 段
" 场景2:与系统剪贴板交互
"+y " 在可视模式下复制到系统剪贴板
"+p " 从系统剪贴板粘贴
" 场景3:删除但不污染剪贴板
"_dw " 删除单词但不影响无名寄存器

推荐配置:如果想让每次复制都自动同步到系统剪贴板,在 .vimrc 中设置 set clipboard=unnamedplus(详见配置章节)。


10. 宏录制#

宏是 Vim 的”自动化录制”——录制一组操作,然后一键回放。

10.1 录制与回放#

q{a-z} " 开始录制到寄存器 a
... " 执行操作
q " 停止录制
@{a-z} " 回放寄存器 a 中的宏
{n}@{a-z} " 回放 n 次
@@ " 回放上次执行的宏
@: " 回放上次命令行命令

10.2 实战示例#

场景:给 100 行每行末尾添加分号

" 手动操作需要 100 次 A;Esc,用宏只需录一次
qa " 开始录制到寄存器 a
A; " 在行末添加 ;
Esc " 回到普通模式
j " 下移一行
q " 停止录制
99@a " 回放 99 次(当前行已处理,还需处理 99 行)

场景:将列表每行转为 Markdown 链接

原始数据:
apple
banana
cherry
目标结果:
- [apple](#apple)
- [banana](#banana)
- [cherry](#cherry)
" 将光标放在第一行,开始录制
qa
I- [ " 行首插入 "- ["
Esc
A](# " 行末追加 "](#"
Esc
p " 粘贴(需要先把单词存入寄存器,这里简化)
" 实际操作更复杂,需要用寄存器
q
" 更简洁的方案:
qa
I- [Esc " 行首加 "- ["
Ea](#Esc " 跳到词末加 "](#"
0 " 回到行首
ye " 复制单词
A " 行末插入
Esc
$j " 下移
q

场景:批量去除行尾空格

qa
$ " 跳到行末
dw " 刔回到行首(如果有空格)
j " 下移
q

宏的技巧:录制宏时,确保每一步都是可重复的——用 0/^ 回到行首,用 w/e 按单词移动,而非依赖绝对位置。

10.3 编辑宏#

宏本质上就是寄存器里的文本,可以编辑:

" 将宏 a 粘贴到文件中
"ap
" 编辑宏内容
" 修改粘贴出来的文本
" 将修改后的内容重新存入寄存器 a
0"ay$
" 现在执行 @a 就是修改后的宏

11. 自定义配置 .vimrc#

11.1 基础配置#

创建 ~/.vimrc 文件:

" ============================================
" Vim 基础配置
" ============================================
" --- 基本设置 ---
set nocompatible " 关闭 Vi 兼容模式
syntax on " 语法高亮
filetype plugin indent on " 文件类型检测+插件+缩进
" --- 编辑体验 ---
set number " 显示行号
set relativenumber " 相对行号(方便用 5j 等跳转)
set cursorline " 高亮当前行
set showmatch " 高亮匹配括号
set wildmenu " 命令行补全菜单
set laststatus=2 " 始终显示状态栏
" --- 缩进 ---
set tabstop=4 " Tab 显示宽度
set shiftwidth=4 " 自动缩进宽度
set expandtab " Tab 转为空格
set autoindent " 自动缩进
set smartindent " 智能缩进
set smarttab " 智能 Tab
" --- 搜索 ---
set ignorecase " 忽略大小写
set smartcase " 智能大小写
set hlsearch " 高亮搜索
set incsearch " 增量搜索
" --- 显示 ---
set wrap " 自动换行
set scrolloff=5 " 光标上下保留 5 行
set sidescrolloff=5 " 水平方向保留 5 列
set colorcolumn=80 " 标记第 80 列
set signcolumn=yes " 始终显示标记列
" --- 文件处理 ---
set encoding=utf-8 " 编码
set fileencoding=utf-8 " 文件编码
set backspace=indent,eol,start " Backspace 键行为
set autoread " 文件被外部修改时自动重载
set hidden " 允许切换缓冲区时不保存
set nobackup " 不创建备份文件
set nowritebackup " 写入时不创建备份
set noswapfile " 不创建交换文件
set undofile " 持久化撤销历史
set undodir=~/.vim/undodir " 撤销文件目录
" --- 剪贴板 ---
set clipboard=unnamedplus " 使用系统剪贴板
" --- 性能 ---
set updatetime=300 " CursorHold 触发时间
set timeoutlen=500 " 按键序列超时
set ttimeoutlen=10 " 终端按键超时
" --- 换行显示 ---
set list " 显示不可见字符
set listchars=tab:▸\ ,eol:¬,trail:·,extends:❯,precedes:❮

11.2 快捷键映射#

" ============================================
" 快捷键映射
" ============================================
" 重新映射 Leader 键
let mapleader = " "
let maplocalleader = "\\"
" 退出插入模式(jj 比 Esc 更顺手)
inoremap jk <Esc>
inoremap kj <Esc>
" 保存
nnoremap <leader>w :w<CR>
" 退出
nnoremap <leader>q :q<CR>
nnoremap <leader>Q :qa!<CR>
" 保存退出
nnoremap <leader>x :x<CR>
" 清除搜索高亮
nnoremap <leader>nh :nohlsearch<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
" 快速缓冲区切换
nnoremap <leader>bn :bn<CR>
nnoremap <leader>bp :bp<CR>
nnoremap <leader>bd :bd<CR>
" 快速标签页
nnoremap <leader>tn :tabnew<CR>
nnoremap <leader>tc :tabclose<CR>
" 复制到系统剪贴板
vnoremap <leader>y "+y
nnoremap <leader>y "+y
nnoremap <leader>Y "+Y
" 从系统剪贴板粘贴
nnoremap <leader>p "+p
nnoremap <leader>P "+P
" 选中全文
nnoremap <leader>a ggVG
" 重新缩进全文
nnoremap <leader>= gg=G
" 快速编辑 vimrc
nnoremap <leader>ev :vsplit $MYVIMRC<CR>
nnoremap <leader>sv :source $MYVIMRC<CR>
" 移动选中行
nnoremap <C-j> :m .+1<CR>==
nnoremap <C-k> :m .-2<CR>==
vnoremap <C-j> :m '>+1<CR>gv=gv
vnoremap <C-k> :m '<-2<CR>gv=gv
" 快速搜索替换当前词
nnoremap <leader>rr :%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>
" 取消高亮
nnoremap <esc> :noh<return><esc>

11.3 文件类型特定设置#

" ============================================
" 文件类型设置
" ============================================
augroup filetype_settings
autocmd!
" Python
autocmd FileType python setlocal tabstop=4 shiftwidth=4 expandtab
autocmd FileType python setlocal colorcolumn=88
" JavaScript / TypeScript
autocmd FileType javascript,typescript setlocal tabstop=2 shiftwidth=2 expandtab
" HTML / CSS
autocmd FileType html,css setlocal tabstop=2 shiftwidth=2 expandtab
" JSON / YAML
autocmd FileType json,yaml setlocal tabstop=2 shiftwidth=2 expandtab
" Go
autocmd FileType go setlocal tabstop=4 shiftwidth=4 noexpandtab
" Markdown
autocmd FileType markdown setlocal wrap linebreak spell
" Shell
autocmd FileType sh,bash setlocal tabstop=2 shiftwidth=2 expandtab
" C / C++
autocmd FileType c,cpp setlocal tabstop=4 shiftwidth=4 expandtab
" Vim Script
autocmd FileType vim setlocal tabstop=2 shiftwidth=2 expandtab foldmethod=marker
augroup END

11.4 状态栏配置#

" ============================================
" 状态栏
" ============================================
set statusline=%< " 截断标记
set statusline+=%f " 文件名(相对路径)
set statusline+=%m " 修改标记
set statusline+=%r " 只读标记
set statusline+=%h " 帮助文件标记
set statusline+=%w " 预览窗口标记
set statusline+=%= " 左右分隔
set statusline+=%{&fileencoding} " 编码
set statusline+=[%{&fileformat}] " 文件格式(unix/dos)
set statusline+=%y " 文件类型
set statusline+=%8l/%-6L " 当前行/总行数
set statusline+=%4c " 列号
set statusline+=%3p%% " 百分比

11.5 完整生产级配置#

将以上所有配置整合,加入更多实用设置:

" ============================================
" .vimrc — 生产级 Vim 配置
" 适用于 Vim 9.0+
" ============================================
" --- 基本设置 ---
set nocompatible
syntax on
filetype plugin indent on
" --- 编辑体验 ---
set number relativenumber
set cursorline
set showmatch
set wildmenu
set wildmode=longest:full,full
set laststatus=2
set showcmd
set ruler
set cmdheight=1
" --- 缩进 ---
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
set smartindent
" --- 搜索 ---
set ignorecase
set smartcase
set hlsearch
set incsearch
" --- 显示 ---
set wrap
set linebreak
set scrolloff=8
set sidescrolloff=8
set colorcolumn=80
set signcolumn=yes
set termguicolors
" --- 文件 ---
set encoding=utf-8
set fileencoding=utf-8
set backspace=indent,eol,start
set autoread
set hidden
set nobackup
set nowritebackup
set noswapfile
set undofile
set undodir=~/.vim/undodir
" --- 剪贴板 ---
set clipboard=unnamedplus
" --- 性能 ---
set updatetime=300
set timeoutlen=500
set ttimeoutlen=10
set lazyredraw
" --- 不可见字符 ---
set list
set listchars=tab:▸\ ,eol:¬,trail:·,extends:❯,precedes:❮
" --- 折叠 ---
set foldmethod=indent
set foldlevel=99
" --- Leader 键 ---
let mapleader = " "
let maplocalleader = "\\"
" --- 快捷键 ---
inoremap jk <Esc>
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>x :x<CR>
nnoremap <leader>nh :nohlsearch<CR>
nnoremap <leader>ev :vsplit $MYVIMRC<CR>
nnoremap <leader>sv :source $MYVIMRC<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
" 缓冲区
nnoremap <S-l> :bn<CR>
nnoremap <S-h> :bp<CR>
nnoremap <leader>d :bd<CR>
" 剪贴板
vnoremap <leader>y "+y
nnoremap <leader>y "+y
" 移动行
nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv
" --- 文件类型 ---
augroup filetype_settings
autocmd!
autocmd FileType python setlocal ts=4 sw=4 sts=4
autocmd FileType javascript,typescript,html,css,json,yaml setlocal ts=2 sw=2 sts=2
autocmd FileType go setlocal ts=4 sw=4 noexpandtab
autocmd FileType markdown setlocal wrap linebreak
autocmd FileType vim setlocal ts=2 sw=2 foldmethod=marker
augroup END
" --- 状态栏 ---
set statusline=%<%f\ %m%r%h%w%=%y\ %{&fenc}\[%{&ff}]\ %8l/%-6L\ %3p%%\ %4c
" --- 撤销目录 ---
if !isdirectory(expand('~/.vim/undodir'))
call mkdir(expand('~/.vim/undodir'), 'p', 0700)
endif

12. 插件管理#

12.1 vim-plug 安装#

vim-plug 是最流行的 Vim 插件管理器:

Terminal window
# Vim
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
# Neovim
curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

12.2 插件配置格式#

.vimrc 中添加:

call plug#begin('~/.vim/plugged')
" --- 在这里添加插件 ---
call plug#end()

修改后重启 Vim,执行 :PlugInstall 安装插件。

12.3 推荐插件#

call plug#begin('~/.vim/plugged')
" === 外观 ===
Plug 'morhetz/gruvbox' " 主题
Plug 'vim-airline/vim-airline' " 状态栏
Plug 'vim-airline/vim-airline-themes' " 状态栏主题
Plug 'ryanoasis/vim-devicons' " 文件图标
" === 文件浏览 ===
Plug 'preservim/nerdtree' " 文件树
Plug 'Xuyuanp/nerdtree-git-plugin' " NERDTree Git 状态
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim' " 模糊搜索
" === 代码编辑 ===
Plug 'tpope/vim-surround' " 环绕操作(cs/ds/ys)
Plug 'tpope/vim-commentary' " 注释(gcc/gc)
Plug 'tpope/vim-repeat' " 增强 . 命令
Plug 'tpope/vim-fugitive' " Git 集成
Plug 'tpope/vim-surround' " 引号/括号环绕
Plug 'jiangmiao/auto-pairs' " 自动配对括号
Plug 'alvan/vim-closetag' " 自动闭合 HTML 标签
Plug 'mattn/emmet-vim' " Emmet 快速编写 HTML
" === 代码补全 ===
Plug 'neoclide/coc.nvim', {'branch': 'release'} " LSP 补全
" === 语法高亮 ===
Plug 'sheerun/vim-polyglot' " 多语言语法包
" === 对齐 ===
Plug 'junegunn/vim-easy-align' " 对齐工具
" === 搜索 ===
Plug 'easymotion/vim-easymotion' " 快速跳转
" === 缩进线 ===
Plug 'Yggdroot/indentLine' " 缩进参考线
" === Color ===
Plug 'nvim-colorizer.lua' " 颜色值可视化
" === 终端 ===
Plug 'voldikss/vim-floaterm' " 浮动终端
call plug#end()

12.4 常用插件操作命令#

:PlugInstall " 安装所有插件
:PlugUpdate " 更新所有插件
:PlugClean " 删除未配置的插件
:PlugUpgrade " 更新 vim-plug 自身
:PlugStatus " 查看插件状态
:PlugDiff " 查看插件变更

12.5 必装插件详解#

vim-surround — 环绕操作:

" 修改环绕字符
cs"' ""hello" 改为 'hello'
cs'<q> " 将 'hello' 改为 <q>hello</q>
cst" " 将 <q>hello</q> 改为 "hello"
" 删除环绕字符
ds" " 删除 "hello" 的引号 → hello
dst " 删除 HTML 标签
" 添加环绕字符
ysiw" " 给当前单词加双引号 → "hello"
ysiw) " 给当前单词加括号 → (hello)
yss" " 给整行加双引号

vim-commentary — 注释:

gcc " 注释/取消注释当前行
gc{motion} " 注释 motion 范围
gc3j " 注释当前行及下面 3 行
gcap " 注释当前段落
gci{ " 注释花括号内的内容

fzf.vim — 模糊搜索:

:Files " 搜索文件
:Lines " 在所有缓冲区搜索行
:Rg " 使用 ripgrep 搜索内容
:Buffers " 切换缓冲区
:Marks " 跳转标记
:Commands " 搜索命令
:History " 搜索历史命令

13. Neovim#

13.1 Neovim 与 Vim 的区别#

特性Vim 9.1Neovim 0.10
配置语言Vim ScriptLua + Vim Script
内嵌终端需插件原生 :terminal
LSP需插件内置 vim.lsp
Treesitter需插件内置 vim.treesitter
异步Vim 8+ 支持原生架构
UI终端可分离 UI(GUI/Web)
启动速度~30ms~30ms
配置目录~/.vim/~/.config/nvim/
配置文件~/.vimrc~/.config/nvim/init.lua

13.2 Neovim Lua 配置入门#

-- ~/.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.ignorecase = true
vim.opt.smartcase = true
vim.opt.hlsearch = true
vim.opt.incsearch = true
vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes"
vim.opt.clipboard = "unnamedplus"
vim.opt.undofile = true
vim.opt.undodir = vim.fn.expand("~/.config/nvim/undodir")
-- Leader 键
vim.g.mapleader = " "
-- 快捷键
vim.keymap.set("i", "jk", "<Esc>")
vim.keymap.set("n", "<leader>w", ":w<CR>")
vim.keymap.set("n", "<leader>q", ":q<CR>")
vim.keymap.set("n", "<leader>nh", ":nohlsearch<CR>")
-- 窗口切换
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")

13.3 Neovim 插件管理(lazy.nvim)#

-- ~/.config/nvim/init.lua
-- 安装 lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- 插件列表
require("lazy").setup({
-- 主题
{ "catppuccin/nvim", name = "catppuccin", priority = 1000 },
-- 状态栏
{ "nvim-lualine/lualine.nvim", dependencies = { "nvim-tree/nvim-web-devicons" } },
-- 文件树
{ "nvim-tree/nvim-tree.lua", dependencies = { "nvim-tree/nvim-web-devicons" } },
-- 模糊搜索
{ "nvim-telescope/telescope.nvim", dependencies = { "nvim-lua/plenary.nvim" } },
-- Treesitter(语法高亮)
{ "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" },
-- LSP
{ "neovim/nvim-lspconfig" },
-- 补全
{ "hrsh7th/nvim-cmp", dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
"L3MON4D3/LuaSnip",
}},
-- 注释
{ "numToStr/Comment.nvim", config = true },
-- 环绕操作
{ "kylechui/nvim-surround", config = true },
-- Git
{ "lewis6991/gitsigns.nvim", config = true },
-- 缩进线
{ "lukas-reineke/indent-blankline.nvim", main = "ibl", config = true },
})

13.4 从 Vim 迁移到 Neovim#

兼容性: Neovim 完全兼容 Vim Script,你的 .vimrc 可以直接用于 Neovim:

Terminal window
# 方法1:直接链接
ln -s ~/.vimrc ~/.config/nvim/init.vim
# 方法2:在 init.vim 中引入
echo 'source ~/.vimrc' > ~/.config/nvim/init.vim

迁移建议:

  1. 先用 init.vim(兼容 Vim Script)过渡
  2. 逐步将配置迁移为 Lua
  3. 利用 Neovim 独有功能(LSP/Treesitter/内嵌终端)

14. Vim + Tmux 工作流#

Vim 和 Tmux 是终端开发的黄金搭档——Tmux 管理窗口布局,Vim 管理代码编辑。

14.1 经典终端开发布局#

┌─────────────────────────────────────────┐
│ Tmux Session: dev │
├──────────────────┬──────────────────────┤
│ │ │
│ Vim │ Terminal │
│ (代码编辑) │ (运行命令/测试) │
│ │ │
├──────────────────┴──────────────────────┤
│ Tmux Status Bar │
└─────────────────────────────────────────┘

14.2 快速启动脚本#

#!/bin/bash
# ~/scripts/dev.sh — 一键启动开发环境
SESSION="dev"
PROJECT_DIR="$HOME/projects/myapp"
# 如果会话已存在,直接连接
tmux has-session -t $SESSION 2>/dev/null
if [ $? == 0 ]; then
tmux attach -t $SESSION
exit 0
fi
# 创建新会话
tmux new-session -d -s $SESSION -c $PROJECT_DIR
# 窗口1:Vim + 终端
tmux split-window -h -t $SESSION:0 -c $PROJECT_DIR
tmux send-keys -t $SESSION:0.0 'vim .' C-m
tmux send-keys -t $SESSION:0.1 'git status' C-m
# 窗口2:日志
tmux new-window -t $SESSION:1 -c $PROJECT_DIR
tmux send-keys -t $SESSION:1 'tail -f logs/app.log' C-m
# 窗口3:服务器
tmux new-window -t $SESSION:2 -c $PROJECT_DIR
tmux send-keys -t $SESSION:2 'npm run dev' C-m
# 连接会话
tmux attach -t $SESSION

14.3 Tmux + Vim 窗口无缝切换#

在 Tmux 和 Vim 中使用相同的快捷键切换窗口:

~/.tmux.conf:

# 启用 Smart Pane Switching
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
" Neovim 版本(更精确)
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

~/.vimrc:

" Vim/Neovim 窗口切换
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l

效果:按 Ctrl+h/j/k/l 时,如果当前在 Vim 中,切换 Vim 窗口;如果在 Tmux 终端中,切换 Tmux 窗格——完全无缝。

14.4 Tmux 复制模式与 Vim 集成#

~/.tmux.conf:

# 使用 Vi 模式
set-window-option -g mode-keys vi
# Vi 风格复制
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel "pbcopy" " macOS
# bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel "xclip -selection clipboard" " Linux

这样在 Tmux 复制模式中按 v 开始选中,y 复制到系统剪贴板——与 Vim 的操作习惯一致。


15. 高级技巧#

15.1 命令重复#

. " 重复上次修改操作(Vim 最重要的按键之一)
@: " 重复上次命令行命令
n / N " 重复搜索
; / , " 重复 f/F/t/T
& " 重复上次 :s 替换

15.2 数字前缀#

几乎所有命令都可以加数字前缀表示重复次数:

3dd " 删除 3 行
5j " 下移 5 行
2yy " 复制 2 行
7x " 删除 7 个字符
3>> " 缩进 3 行
4w " 向前移动 4 个单词
2fa " 在当前行找第 2 个 a

15.3 插入特殊字符#

Ctrl+v {digit} " 按十进制 ASCII 码插入字符
Ctrl+v x{hex} " 按十六进制插入
Ctrl+v u{hex} " 按 Unicode 插入
Ctrl+k {digraph} " 插入二合字符(如 Ctrl+k -> 插入 →)

15.4 录制命令到寄存器并执行#

" 将命令序列写入寄存器
:let @a = "ggVG:s/old/new/g\<CR>"
" 执行
@a

15.5 过滤外部命令#

:!ls " 执行 ls 并查看输出
:w !sudo tee % " 以 root 权限保存
:%!sort " 对所有行排序
:%!jq . " 格式化 JSON
:'<,'>!column -t " 对选中区域对齐
!!date " 用 date 命令的输出替换当前行

15.6 会话保存与恢复#

:mksession! dev.vim " 保存当前会话(窗口/标签页/缓冲区布局)
:source dev.vim " 恢复会话

15.7 多行编辑(块可视模式进阶)#

" 在多行行首插入
Ctrl+v " 块可视模式
jjj " 选中 4 行
I " 插入模式(注意是大写 I)
# " 输入注释
Esc " 所有选中行都会添加 #
" 在多行行末追加
Ctrl+v
jjj
$ " 扩展到行末
A " 追加(注意是大写 A)
; " 输入分号
Esc " 所有行都添加 ;

注意:块可视模式插入时,只有输入完按 Esc 才会应用到所有行——输入过程中只看到第一行变化是正常的。

15.8 quickfix 列表#

:copen " 打开 quickfix 窗口
:cclose " 关闭 quickfix 窗口
:cnext " 下一个错误
:cprev " 上一个错误
:cfirst " 第一个错误
:clast " 最后一个错误
:cnfile " 下一个文件的错误
:grep keyword *.py " 搜索并将结果放入 quickfix
:vimgrep /pattern/ **/*.py " Vim 内置 grep

15.9 拼写检查#

:set spell " 开启拼写检查
:set spelllang=en_us " 设置语言
]s " 下一个拼写错误
[s " 上一个拼写错误
z= " 查看建议
zg " 添加到词典(good)
zw " 标记为错误(wrong)
zug " 撤销 zg

15.10 加密文件#

:set password " Vim 9.0+ 新加密方式
:X " 设置密码(旧版 blowfish2)

16. 常见问题排查#

16.1 退出相关问题#

问题:Vim 打开后不知道怎么退出

解决:
1. 按 Esc 确保在普通模式
2. 输入 :q! 强制退出(不保存)
3. 或输入 :wq 保存退出

问题:E37: No write since last change

原因:有未保存的修改
解决:用 :wq 保存退出,或 :q! 强制退出不保存

问题:E162: No write since last change for buffer

原因:切换缓冲区时当前缓冲区有修改
解决:
1. 先 :w 保存
2. 或 :set hidden 允许隐藏有修改的缓冲区
3. 或 :q! 关闭当前缓冲区

16.2 编码问题#

问题:中文乱码

" 在 .vimrc 中设置
set encoding=utf-8
set fileencoding=utf-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1

问题:文件有 ^M 字符(Windows 换行符)

" 查看当前文件格式
:set fileformat?
" 转为 Unix 格式
:set fileformat=unix
:w
" 或直接替换
:%s/\r//g

16.3 剪贴板问题#

问题:无法与系统剪贴板互通

" 检查是否支持剪贴板
:echo has('clipboard')
" 输出 1 表示支持,0 表示不支持
" 如果不支持,安装带 clipboard 支持的版本
" Ubuntu: sudo apt install vim-gtk3
" macOS: brew install vim

问题:粘贴时格式错乱

" 进入粘贴模式再粘贴
:set paste
" 粘贴内容...
:set nopaste
" 或使用系统剪贴板粘贴
"+p

16.4 性能问题#

问题:Vim 打开大文件很慢

" 打开大文件时禁用部分功能
vim -u NONE -n large_file.log
" 或在 vimrc 中添加
if line('$') > 10000
set nosyntax
set norelativenumber
set lazyredraw
endif

问题:插件导致启动慢

" 分析启动时间
vim --startuptime vim-startup.log
" 查看哪些插件最耗时
sort vim-startup.log by time column

16.5 颜色问题#

问题:终端颜色不对

" 确保终端支持 256 色或 truecolor
set t_Co=256
set termguicolors " 如果终端支持 truecolor
" 检查终端是否支持 truecolor
echo $COLORTERM
" 应该输出 truecolor 或 24bit

16.6 常见错误速查表#

错误信息含义解决方案
E37: No write since last change有未保存修改:w:q!
E162: No write since last change for buffer缓冲区有修改:w:set hidden
E486: Pattern not found搜索模式没找到检查搜索词
E553: No more items to replace没有更多匹配项正常,替换完毕
E212: Can't open file for writing无法写入文件检查权限或用 :w !sudo tee %
E173: 5 more buffer(s) with a warning多个缓冲区有修改:wqa 或逐个处理
E384: search hit TOP without match搜索到文件顶部无匹配尝试反向搜索或检查搜索词
E861: Cannot open aux file无法创建辅助文件检查目录权限
^M 字符Windows 换行符:set ff=unix
退格键无效backspace 设置问题:set backspace=indent,eol,start

17. 速查表#

17.1 命令行速查#

Terminal window
vim file.txt # 打开文件
vim + file.txt # 打开并跳到最后一行
vim +42 file.txt # 打开并跳到第 42 行
vim +/pattern file.txt # 打开并跳到第一个匹配
vim -R file.txt # 只读模式打开
vim -d file1 file2 # diff 模式比较两个文件
vim -O file1 file2 # 垂直分屏打开两个文件
vim -o file1 file2 # 水平分屏打开两个文件
vim -p file1 file2 file3 # 标签页打开多个文件
vim -r # 恢复交换文件
vim -u NONE file.txt # 不加载配置文件
vim --startuptime log.txt # 记录启动时间

17.2 全部快捷键速查#

移动:

按键功能
h j k l左 下 上 右
w b e下一词首 / 上一词首 / 词尾
W B E同上(以空格分词)
0 ^ $行首 / 首字符 / 行末
gg G文件头 / 文件尾
{n}G跳到第 n 行
H M L屏幕顶 / 中 / 底
Ctrl+d/u下/上翻半页
Ctrl+f/b下/上翻整页
%匹配括号
* #下/上搜索当前词
f{x} t{x}跳到/跳到 x 前
{ }上/下一个段落
( )上/下一句

编辑:

按键功能
i a o前插 / 后插 / 下方新行
I A O行首插 / 行末插 / 上方新行
x dd yy p删字符 / 删行 / 复制行 / 粘贴
dw cw yw删/改/复制词
D C删/改到行末
u Ctrl+r撤销 / 重做
r R替换字符 / 替换模式
~切换大小写
>> <<右/左缩进
=自动缩进
J合并行
.重复上次操作

搜索替换:

按键功能
/ ?下/上搜索
n N下/上个匹配
* #搜索当前词
:s/old/new/替换当前行第一个
:s/old/new/g替换当前行所有
:%s/old/new/g全文替换
:%s/old/new/gc全文替换并确认

文本对象:

按键功能
ciw修改当前单词
daw删除单词(含空格)
ci" ci'修改引号内
ci( ci{ ci[修改括号内
cit修改 HTML 标签内
cit修改 HTML 标签内
dat删除 HTML 标签
vap选中段落

窗口:

按键功能
:sp :vs水平/垂直分屏
Ctrl+w h/j/k/l切换窗口
Ctrl+w =等分窗口
Ctrl+w _最大化高度
`Ctrl+w`
Ctrl+w c关闭窗口
Ctrl+w o仅保留当前窗口

18. 最佳实践#

18.1 学习路径#

第 1 周:生存基础
├── 四种模式(Normal/Insert/Visual/Command)
├── 基本移动(hjkl、w/b/e、gg/G)
├── 基本编辑(i/a/o、x/dd/yy/p、u)
├── 保存退出(:w/:q/:wq/:q!)
└── 搜索(/、n、N)
第 2 周:效率提升
├── 行内跳转(0、^、$、f/F/t/T)
├── 文本对象(ciw、da"、ci()
├── 可视模式(v/V/Ctrl+v)
├── 替换(:%s/old/new/g)
└── . 重复命令
第 3 周:进阶操作
├── 寄存器("ayy、"ap)
├── 宏录制(q...q、@a)
├── 多文件编辑(buffer/window/tab)
├── 标记(ma、`a)
└── 块编辑(Ctrl+v + I/A)
第 4 周:配置与插件
├── .vimrc 基础配置
├── vim-plug 插件管理
├── 常用插件安装
├── 自定义快捷键
└── Tmux + Vim 集成

18.2 十条核心最佳实践#

  1. Esc 是你的家 — 完成操作立即回到普通模式
  2. 用文本对象代替手动选中ciwvwwd 更快更准确
  3. . 重复 — 思考如何让操作可重复
  4. 少用插入模式 — 普通模式才是 Vim 的主场
  5. 搜索代替滚动 — 用 /* 跳转,不要 Ctrl+f 翻页找
  6. 配置你的 .vimrc — 默认配置只是起点
  7. 学会 f/t 跳转f;$hhh 高效得多
  8. 用数字前缀3ddddd 高效
  9. 不追求完全替代 IDE — Vim 和 IDE 各有场景
  10. 每天学一个新命令:help usr_01.txt 开始系统学习

18.3 场景推荐#

场景推荐工具
SSH 改配置文件Vim(服务器标配)
远程调试代码Neovim 或 Vim
日常大型项目开发VS Code + Vim 插件
快速查看文件vim -Rless
Git commitVim(默认编辑器)
批量文本处理Vim 宏 + 命令行管道
写 MarkdownNeovim 或 VS Code
终端多窗口开发Tmux + Vim/Neovim

18.4 帮助系统#

:help " 帮助首页
:help usr_01.txt " 用户手册第一章
:help quickref " 快速参考
:help :s " :s 命令帮助
:help i_CTRL-N " 插入模式 Ctrl+N
:help v_b " 块可视模式
:help 'number' " number 选项
:helpgrep keyword " 全文搜索帮助

学习建议:help usr_01.txt:help usr_44.txt 是 Vim 自带的完整教程,花一周通读一遍受益终身。

18.5 在线资源#

  • Vim Golf — 用最少按键完成任务,锻炼 Vim 技巧
  • Vim Adventures — 用游戏学习 Vim
  • OpenVim — 在线交互式 Vim 教程
  • :help — 永远是最好的文档

总结#

Vim 的学习曲线确实陡峭,但它是一次学习终身受用的投资。以下是核心要点回顾:

知识点核心命令
模式切换Esc → 普通模式,i/a/o → 插入模式
移动hjkl wb e 0^$ gg G f t
编辑x dd yy p cw dw u Ctrl+r
搜索替换/ n N :%s/old/new/g
文本对象ciw da" ci( dap
多文件:e :bn :bp :sp :vs :tabnew
q{a}...q @{a}
配置~/.vimrc
插件vim-plug :PlugInstall

记住三个核心规律:

  1. 普通模式是家 — 任何操作完成后回到普通模式
  2. 语法化思维 — 动词 + 名词(d + iw = 删除单词)
  3. 可重复性 — 让操作可以用 . 重复

如果你只记住一句话:Esc,然后 :wq 保存退出。 剩下的慢慢学。


推荐阅读#

Vim 编辑器完全指南:从入门到精通 | 2026 最新实践
https://971918.xyz/posts/docs/vim-complete-guide/
作者
九所长
发布于
2026-07-05
许可协议
CC BY-NC-SA 4.0