Vim 编辑器完全指南:从入门到精通 | 2026 最新实践
你有没有遇到过这些场景:
- SSH 到服务器改配置文件,
vi打开后一顿乱按,改了半天不知道怎么保存退出 - 远程调试代码,VS Code Remote 连不上,只能用终端,却连复制粘贴都费劲
- 看同事在 Vim 里双手翻飞,光标像长了眼睛一样精准跳转,自己却还在 hjkl 一下一下挪
Vim 是 Linux 服务器上唯一保证可用的文本编辑器——和 SSH 一样基础,但大多数人从未真正学会它。
本文从零开始,系统讲解 Vim 的完整知识体系:
- 四种模式与核心概念
- 移动、编辑、搜索替换全操作
- 多文件编辑(缓冲区/窗口/标签页)
- 可视化模式、寄存器、宏录制
- 文本对象(
ciw、da"等高效操作) - 自定义配置
.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
| 特性 | Vim | Neovim | VS Code |
|---|---|---|---|
| 出现年份 | 1991 | 2014 | 2015 |
| 配置语言 | Vim Script | Lua + Vim Script | JSON |
| 内嵌终端 | ❌ | ✅ | ✅ |
| LSP 原生支持 | ❌ | ✅ | ✅ |
| 异步任务 | Vim 8+ | ✅ 原生 | ✅ |
| 插件生态 | 成熟但趋缓 | 活跃增长 | 最活跃 |
| 启动速度 | 极快(<50ms) | 极快(<50ms) | 较慢(1-3s) |
| 服务器可用 | ✅ 默认安装 | 需手动安装 | ❌ 需 Remote |
| 学习曲线 | 陡峭 | 陡峭(与 Vim 一致) | 平缓 |
| 适合场景 | 服务器编辑/快速修改 | 日常开发/服务器 | 日常开发 |
选择建议:
- 服务器运维 → Vim(默认安装,零配置可用)
- 终端开发 → Neovim(Lua 配置 + LSP + Treesitter)
- 图形界面开发 → VS Code + Vim 插件(兼顾效率和图形化)
1.3 Vim 的设计哲学
Vim 的核心设计理念是 「编辑器的速度应与思维速度匹配」:
- 模式编辑 — 不同模式做不同的事,按键含义随模式变化
- 双手不离键盘 — 所有操作通过键盘完成,鼠标是效率瓶颈
- 语法化命令 — 命令有语法结构(动词 + 名词),可组合
- 可重复 —
.重复上次操作,高效操作的基石
核心理解:Vim 不是”难用的编辑器”,而是”需要学习的编辑器”。一旦度过初始学习曲线,效率会指数级提升。
2. 安装
2.1 各平台安装
# Ubuntu / Debiansudo apt update && sudo apt install vim
# CentOS / RHEL / Fedorasudo dnf install vim-enhanced # Fedora / RHEL 8+sudo yum install vim-enhanced # CentOS 7
# macOS(系统自带的是精简版,建议安装完整版)brew install vim
# Arch Linuxsudo pacman -S vim
# Windows# 方法1: 使用 wingetwinget install vim.vim
# 方法2: 使用 scoopscoop install vim
# 方法3: 使用 chocochoco install vim2.2 验证安装
vim --version输出中关注以下信息:
VIM - Vi IMproved 9.1 (2024 Jan 02)Compiled Mar 15 2026 00:00:00Normal 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-gtk或vim-gtk3;macOS 上用brew install vim。
2.3 Neovim 安装
# Ubuntu / Debiansudo apt install neovim
# macOSbrew install neovim
# Fedora / RHEL 8+sudo dnf install neovim
# Arch Linuxsudo pacman -S neovim
# Windowswinget install Neovim.Neovim3. 四种模式
模式是 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)
从普通模式进入插入模式的多种方式:
| 按键 | 含义 | 光标位置 |
|---|---|---|
i | insert | 在光标前插入 |
a | append | 在光标后插入 |
I | 大写 I | 在行首插入 |
A | 大写 A | 在行末插入 |
o | open | 在下方新开一行 |
O | 大写 O | 在上方新开一行 |
s | substitute | 删除光标字符并进入插入 |
S | 大写 S | 删除整行并进入插入 |
cw | change word | 删除当前单词并进入插入 |
cc | change 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 " 搜索 functionEnter " 跳到匹配处
" 实战:在括号间跳转% " 光标在 ( 上,按 % 跳到匹配的 )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 " 将当前字符替换为 15.5 缩进
| 按键 | 含义 |
|---|---|
>> | 当前行右缩进 |
<< | 当前行左缩进 |
>{motion} | motion 范围右缩进 |
<{motion} | motion 范围左缩进 |
= | 自动缩进当前行 |
gg=G | 全文自动缩进 |
=i{ | 自动缩进当前花括号块 |
" 实战:全文格式化gg=G " 跳到文件头,自动缩进到文件末尾
" 实战:缩进 5 行5>> " 当前行及下面 4 行右缩进6. 搜索与替换
6.1 搜索
/keyword " 向下搜索 keyword?keyword " 向上搜索 keywordn " 跳到下一个匹配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)?| 按键 | 含义 |
|---|---|
y | yes,替换 |
n | no,不替换 |
a | all,替换剩余所有 |
q | quit,退出替换 |
l | last,替换后退出 |
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":/g7. 多文件编辑
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| 标记 | 含义 |
|---|---|
% | 当前缓冲区 |
# | 交替缓冲区(上次访问的) |
a | active(有窗口显示) |
h | hidden(隐藏,未显示) |
+ | 有未保存修改 |
- | 不可修改 |
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}- operator:
d(删除)、c(修改)、y(复制)、v(选中) - a/i:
a= around(含周围分隔符),i= inside(不含分隔符) - object:文本对象类型
8.2 常用文本对象
| 对象 | 含义 | 示例 |
|---|---|---|
w | word | daw 删除整个单词 |
W | WORD | daW 删除整个 WORD |
s | sentence | das 删除整个句子 |
p | paragraph | dap 删除整个段落 |
t | XML/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 " 开始录制到寄存器 aA; " 在行末添加 ;Esc " 回到普通模式j " 下移一行q " 停止录制
99@a " 回放 99 次(当前行已处理,还需处理 99 行)场景:将列表每行转为 Markdown 链接
原始数据:applebananacherry
目标结果:- [apple](#apple)- [banana](#banana)- [cherry](#cherry)" 将光标放在第一行,开始录制qaI- [ " 行首插入 "- ["EscA](# " 行末追加 "](#"Escp " 粘贴(需要先把单词存入寄存器,这里简化)" 实际操作更复杂,需要用寄存器q
" 更简洁的方案:qaI- [Esc " 行首加 "- ["Ea](#Esc " 跳到词末加 "](#"0 " 回到行首ye " 复制单词A " 行末插入Esc$j " 下移q场景:批量去除行尾空格
qa$ " 跳到行末dw " 刔回到行首(如果有空格)j " 下移q宏的技巧:录制宏时,确保每一步都是可重复的——用
0/^回到行首,用w/e按单词移动,而非依赖绝对位置。
10.3 编辑宏
宏本质上就是寄存器里的文本,可以编辑:
" 将宏 a 粘贴到文件中"ap
" 编辑宏内容" 修改粘贴出来的文本
" 将修改后的内容重新存入寄存器 a0"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>hnnoremap <C-j> <C-w>jnnoremap <C-k> <C-w>knnoremap <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 "+ynnoremap <leader>y "+ynnoremap <leader>Y "+Y
" 从系统剪贴板粘贴nnoremap <leader>p "+pnnoremap <leader>P "+P
" 选中全文nnoremap <leader>a ggVG
" 重新缩进全文nnoremap <leader>= gg=G
" 快速编辑 vimrcnnoremap <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=gvvnoremap <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=markeraugroup END11.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 nocompatiblesyntax onfiletype plugin indent on
" --- 编辑体验 ---set number relativenumberset cursorlineset showmatchset wildmenuset wildmode=longest:full,fullset laststatus=2set showcmdset rulerset cmdheight=1
" --- 缩进 ---set tabstop=4set shiftwidth=4set expandtabset autoindentset smartindent
" --- 搜索 ---set ignorecaseset smartcaseset hlsearchset incsearch
" --- 显示 ---set wrapset linebreakset scrolloff=8set sidescrolloff=8set colorcolumn=80set signcolumn=yesset termguicolors
" --- 文件 ---set encoding=utf-8set fileencoding=utf-8set backspace=indent,eol,startset autoreadset hiddenset nobackupset nowritebackupset noswapfileset undofileset undodir=~/.vim/undodir
" --- 剪贴板 ---set clipboard=unnamedplus
" --- 性能 ---set updatetime=300set timeoutlen=500set ttimeoutlen=10set lazyredraw
" --- 不可见字符 ---set listset listchars=tab:▸\ ,eol:¬,trail:·,extends:❯,precedes:❮
" --- 折叠 ---set foldmethod=indentset 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>hnnoremap <C-j> <C-w>jnnoremap <C-k> <C-w>knnoremap <C-l> <C-w>l
" 缓冲区nnoremap <S-l> :bn<CR>nnoremap <S-h> :bp<CR>nnoremap <leader>d :bd<CR>
" 剪贴板vnoremap <leader>y "+ynnoremap <leader>y "+y
" 移动行nnoremap <A-j> :m .+1<CR>==nnoremap <A-k> :m .-2<CR>==vnoremap <A-j> :m '>+1<CR>gv=gvvnoremap <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=markeraugroup 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)endif12. 插件管理
12.1 vim-plug 安装
vim-plug 是最流行的 Vim 插件管理器:
# Vimcurl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
# Neovimcurl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim12.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" 的引号 → hellodst " 删除 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.1 | Neovim 0.10 |
|---|---|---|
| 配置语言 | Vim Script | Lua + 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 = truevim.opt.relativenumber = truevim.opt.tabstop = 4vim.opt.shiftwidth = 4vim.opt.expandtab = truevim.opt.smartindent = truevim.opt.wrap = falsevim.opt.ignorecase = truevim.opt.smartcase = truevim.opt.hlsearch = truevim.opt.incsearch = truevim.opt.termguicolors = truevim.opt.scrolloff = 8vim.opt.signcolumn = "yes"vim.opt.clipboard = "unnamedplus"vim.opt.undofile = truevim.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.nvimlocal 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, })endvim.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:
# 方法1:直接链接ln -s ~/.vimrc ~/.config/nvim/init.vim
# 方法2:在 init.vim 中引入echo 'source ~/.vimrc' > ~/.config/nvim/init.vim迁移建议:
- 先用
init.vim(兼容 Vim Script)过渡 - 逐步将配置迁移为 Lua
- 利用 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/nullif [ $? == 0 ]; then tmux attach -t $SESSION exit 0fi
# 创建新会话tmux new-session -d -s $SESSION -c $PROJECT_DIR
# 窗口1:Vim + 终端tmux split-window -h -t $SESSION:0 -c $PROJECT_DIRtmux send-keys -t $SESSION:0.0 'vim .' C-mtmux send-keys -t $SESSION:0.1 'git status' C-m
# 窗口2:日志tmux new-window -t $SESSION:1 -c $PROJECT_DIRtmux send-keys -t $SESSION:1 'tail -f logs/app.log' C-m
# 窗口3:服务器tmux new-window -t $SESSION:2 -c $PROJECT_DIRtmux send-keys -t $SESSION:2 'npm run dev' C-m
# 连接会话tmux attach -t $SESSION14.3 Tmux + Vim 窗口无缝切换
在 Tmux 和 Vim 中使用相同的快捷键切换窗口:
~/.tmux.conf:
# 启用 Smart Pane Switchingis_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>hnnoremap <C-j> <C-w>jnnoremap <C-k> <C-w>knnoremap <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-selectionbind-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 个 a15.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>"
" 执行@a15.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+vjjj$ " 扩展到行末A " 追加(注意是大写 A); " 输入分号Esc " 所有行都添加 ;注意:块可视模式插入时,只有输入完按
Esc才会应用到所有行——输入过程中只看到第一行变化是正常的。
15.8 quickfix 列表
:copen " 打开 quickfix 窗口:cclose " 关闭 quickfix 窗口:cnext " 下一个错误:cprev " 上一个错误:cfirst " 第一个错误:clast " 最后一个错误:cnfile " 下一个文件的错误:grep keyword *.py " 搜索并将结果放入 quickfix:vimgrep /pattern/ **/*.py " Vim 内置 grep15.9 拼写检查
:set spell " 开启拼写检查:set spelllang=en_us " 设置语言]s " 下一个拼写错误[s " 上一个拼写错误z= " 查看建议zg " 添加到词典(good)zw " 标记为错误(wrong)zug " 撤销 zg15.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-8set fileencoding=utf-8set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1问题:文件有 ^M 字符(Windows 换行符)
" 查看当前文件格式:set fileformat?
" 转为 Unix 格式:set fileformat=unix:w
" 或直接替换:%s/\r//g16.3 剪贴板问题
问题:无法与系统剪贴板互通
" 检查是否支持剪贴板:echo has('clipboard')" 输出 1 表示支持,0 表示不支持
" 如果不支持,安装带 clipboard 支持的版本" Ubuntu: sudo apt install vim-gtk3" macOS: brew install vim问题:粘贴时格式错乱
" 进入粘贴模式再粘贴:set paste" 粘贴内容...:set nopaste
" 或使用系统剪贴板粘贴"+p16.4 性能问题
问题:Vim 打开大文件很慢
" 打开大文件时禁用部分功能vim -u NONE -n large_file.log
" 或在 vimrc 中添加if line('$') > 10000 set nosyntax set norelativenumber set lazyredrawendif问题:插件导致启动慢
" 分析启动时间vim --startuptime vim-startup.log
" 查看哪些插件最耗时sort vim-startup.log by time column16.5 颜色问题
问题:终端颜色不对
" 确保终端支持 256 色或 truecolorset t_Co=256set termguicolors " 如果终端支持 truecolor
" 检查终端是否支持 truecolorecho $COLORTERM" 应该输出 truecolor 或 24bit16.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 命令行速查
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 十条核心最佳实践
- Esc 是你的家 — 完成操作立即回到普通模式
- 用文本对象代替手动选中 —
ciw比vwwd更快更准确 - 用
.重复 — 思考如何让操作可重复 - 少用插入模式 — 普通模式才是 Vim 的主场
- 搜索代替滚动 — 用
/或*跳转,不要 Ctrl+f 翻页找 - 配置你的 .vimrc — 默认配置只是起点
- 学会 f/t 跳转 —
f;比$hhh高效得多 - 用数字前缀 —
3dd比ddd高效 - 不追求完全替代 IDE — Vim 和 IDE 各有场景
- 每天学一个新命令 —
:help usr_01.txt开始系统学习
18.3 场景推荐
| 场景 | 推荐工具 |
|---|---|
| SSH 改配置文件 | Vim(服务器标配) |
| 远程调试代码 | Neovim 或 Vim |
| 日常大型项目开发 | VS Code + Vim 插件 |
| 快速查看文件 | vim -R 或 less |
| Git commit | Vim(默认编辑器) |
| 批量文本处理 | Vim 宏 + 命令行管道 |
| 写 Markdown | Neovim 或 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 |
记住三个核心规律:
- 普通模式是家 — 任何操作完成后回到普通模式
- 语法化思维 — 动词 + 名词(
d+iw= 删除单词) - 可重复性 — 让操作可以用
.重复
如果你只记住一句话:按
Esc,然后:wq保存退出。 剩下的慢慢学。
推荐阅读
- SSH 完全指南:从远程连接到安全加固 — Vim 的最佳搭档
- Tmux 终端复用器完全指南 — 与 Vim 组成终端开发黄金组合
- Linux 常用命令速查手册 — Vim 运行在终端中,终端命令同样重要
- Nginx 反向代理配置实战 — 服务器配置文件编辑必备 Vim
- Git 高级技巧与最佳实践 — Git 默认使用 Vim 作为编辑器