一、模式切换
#Vim 是模态编辑器,操作必须在对应模式下进行。
| 模式 | 含义 | 进入方式 |
|---|
| Normal | 普通模式(默认) | Esc / Ctrl+c |
| Insert | 插入模式(输入文本) | i/a/o 等 |
| Visual | 可视模式(选择文本) | v/V/Ctrl+v |
| Command | 命令行模式 | : |
| Replace | 替换模式 | R |
Normal --i/a/o/I/A/O/s/S/c--> Insert
Normal --v/V/Ctrl+v----------> Visual
Normal --:--------------------> Command
Normal --R--------------------> Replace
Insert/Visual/Command --Esc--> Normal
1.1 进入 Insert 模式的方式
#| 按键 | 含义 |
|---|
i | 光标前插入 |
a | 光标后插入 |
I | 行首插入(第一个非空字符前) |
A | 行尾插入 |
o | 在当前行下方新建一行并插入 |
O | 在当前行上方新建一行并插入 |
s | 删除当前字符并进入插入模式 |
S | 删除当前行内容并进入插入模式 |
c + 动作 | 删除指定范围并进入插入模式(如 cw 删词) |
C | 删除到行尾并进入插入模式 |
二、移动
#2.1 基础移动
#h 左
j 下
k 上
l 右
# 推荐关闭方向键依赖,强迫自己用 hjkl
2.2 词级移动
#| 按键 | 含义 |
|---|
w | 下一个词首(word,以标点分隔) |
W | 下一个词首(WORD,以空白分隔) |
b | 上一个词首 |
B | 上一个词首(WORD) |
e | 当前词末(或下一词末) |
E | 当前词末(WORD) |
ge | 上一词末 |
2.3 行内移动
#| 按键 | 含义 |
|---|
0 | 行首(第0列) |
^ | 行首第一个非空字符 |
$ | 行尾 |
g_ | 行尾最后一个非空字符 |
f{char} | 行内向右找 char(光标移到 char 上) |
F{char} | 行内向左找 char |
t{char} | 行内向右找 char(光标移到 char 前一位) |
T{char} | 行内向左找 char |
; | 重复上一次 f/F/t/T |
, | 反向重复上一次 f/F/t/T |
% | 跳转到匹配的括号/括弧 |
2.4 行级移动
#| 按键 | 含义 |
|---|
gg | 文件首行 |
G | 文件末行 |
{n}G | 跳到第 n 行 |
{n}gg | 跳到第 n 行 |
:{n} | 跳到第 n 行(命令模式) |
+ | 下一行行首 |
- | 上一行行首 |
2.5 屏幕移动
#| 按键 | 含义 |
|---|
H | 屏幕顶部第一行 |
M | 屏幕中间行 |
L | 屏幕底部最后一行 |
Ctrl+f | 向下翻页 |
Ctrl+b | 向上翻页 |
Ctrl+d | 向下翻半页 |
Ctrl+u | 向上翻半页 |
Ctrl+e | 屏幕向下滚动一行(光标不动) |
Ctrl+y | 屏幕向上滚动一行 |
zz | 将当前行移到屏幕中央 |
zt | 将当前行移到屏幕顶部 |
zb | 将当前行移到屏幕底部 |
三、编辑操作
#3.1 删除
#| 按键 | 含义 |
|---|
x | 删除光标处字符 |
X | 删除光标前字符(相当于 Backspace) |
dw | 删除到词尾(含空格) |
diw | 删除词(不含空格,inner word) |
dd | 删除当前行 |
D | 删除到行尾(同 d$) |
d0 | 删除到行首 |
d^ | 删除到行首第一个非空字符 |
dG | 删除到文件末尾 |
dgg | 删除到文件开头 |
{n}dd | 删除 n 行 |
dit | 删除 HTML 标签内容(inner tag) |
di" | 删除双引号内内容 |
di( | 删除括号内内容 |
da" | 删除双引号及其内容(around) |
注意:Vim 的"删除"实际上是剪切,内容存入寄存器。
3.2 复制与粘贴
#| 按键 | 含义 |
|---|
yy | 复制当前行 |
Y | 复制当前行(同 yy) |
yw | 复制到词尾 |
yiw | 复制当前词 |
y$ | 复制到行尾 |
{n}yy | 复制 n 行 |
p | 粘贴到光标后(行则在下方) |
P | 粘贴到光标前(行则在上方) |
]p | 粘贴并调整缩进 |
3.3 替换
#| 按键 | 含义 |
|---|
r{char} | 替换当前字符为 char |
R | 进入替换模式(逐字符覆盖) |
~ | 切换大小写 |
g~{motion} | 切换指定范围大小写 |
gU{motion} | 转大写(如 gUiw 当前词转大写) |
gu{motion} | 转小写 |
3.4 撤销与重做
#| 按键 | 含义 |
|---|
u | 撤销 |
U | 撤销当前行所有修改 |
Ctrl+r | 重做(反撤销) |
. | 重复上一个修改操作(极其强大) |
四、搜索与替换
#4.1 搜索
#/pattern 向下搜索(支持正则)
?pattern 向上搜索
n 下一个匹配
N 上一个匹配
* 搜索光标处单词(向下)
# 搜索光标处单词(向上)
g* 搜索含光标处词的所有词(不限整词)
# 清除搜索高亮
:noh
# 或
:nohlsearch
4.2 替换语法(:s 命令)
#:s/old/new/ " 替换当前行第一个匹配
:s/old/new/g " 替换当前行所有匹配
:%s/old/new/g " 全文替换所有匹配
:%s/old/new/gc " 全文替换,逐个确认(y/n/a/q/l)
:%s/old/new/gi " 全文替换,忽略大小写
:5,20s/old/new/g " 替换第5-20行
" 正则替换示例
:%s/\s\+$// " 删除行尾空白
:%s/^/ / " 每行行首添加4个空格
:%s/\t/ /g " Tab 替换为2个空格
:%s/foo\(bar\)/\1/g " 删除 foo,保留 bar(捕获组)
" 确认替换时的响应键
" y 替换
" n 跳过
" a 全部替换(不再确认)
" q 退出
" l 替换当前后退出
" Ctrl+e/y 滚动屏幕查看上下文
4.3 全局命令 :g
#:g/pattern/d " 删除所有包含 pattern 的行
:g/^$/d " 删除所有空行
:g/^#/d " 删除所有注释行(以#开头)
:g/pattern/p " 打印所有包含 pattern 的行
:g!/pattern/d " 删除不包含 pattern 的行(:v 同效)
:g/pattern/m$ " 将匹配行移到文件末尾
:g/pattern/norm dw " 对每个匹配行执行 normal 命令
五、多文件操作
#5.1 Buffer(缓冲区)
#:ls " 列出所有 buffer
:b 2 " 切换到 buffer 2
:bn " 下一个 buffer
:bp " 上一个 buffer
:bd " 关闭当前 buffer(不退出 Vim)
:e filename " 打开文件到新 buffer
:w " 保存当前 buffer
:wa " 保存所有 buffer
:qa " 关闭所有 buffer(全部退出)
:qa! " 强制关闭所有(放弃修改)
5.2 Tab(标签页)
#:tabnew " 新建 tab
:tabnew filename " 在新 tab 打开文件
:tabn " 下一个 tab(gt)
:tabp " 上一个 tab(gT)
:tabc " 关闭当前 tab
:tabo " 关闭其他所有 tab
:tabs " 列出所有 tab
{n}gt " 切换到第 n 个 tab
5.3 Split(分屏)
#:sp filename " 水平分屏打开文件
:vsp filename " 垂直分屏打开文件
Ctrl+w s " 水平分屏(当前文件)
Ctrl+w v " 垂直分屏
Ctrl+w h/j/k/l " 在分屏间移动
Ctrl+w H/J/K/L " 将当前分屏移到对应方向
Ctrl+w = " 均分所有分屏
Ctrl+w +/- " 调整高度
Ctrl+w >/< " 调整宽度
Ctrl+w _ " 最大化当前分屏高度
Ctrl+w | " 最大化当前分屏宽度
Ctrl+w q " 关闭当前分屏
六、实用技巧
#6.1 宏录制与执行
#qa " 开始录制宏到寄存器 a
... " 执行一系列操作
q " 停止录制
@a " 执行寄存器 a 中的宏
@@ " 重复执行上一次宏
10@a " 执行宏 10 次
" 示例:给每行末尾添加分号
" 将光标移到第一行
qa " 开始录制
A; " 行尾插入 ;
Esc " 退出插入
j " 下移一行
q " 停止录制
100@a " 重复100次(多执行无影响)
6.2 寄存器
#"ayy " 复制当前行到寄存器 a
"ap " 粘贴寄存器 a 的内容
"byiw " 复制当前词到寄存器 b
:reg " 查看所有寄存器内容
:reg a " 查看寄存器 a
" 特殊寄存器
" "" 未命名寄存器(默认 d/y 操作存到这里)
" "0 最近一次 yank 的内容(不受 d 影响)
" "+ 系统剪贴板
" "* 选择区(X11 中间键粘贴)
" "/ 最后一次搜索
" ": 最后一次命令
" ". 最后插入的文本
" "% 当前文件名
" 粘贴系统剪贴板(需要编译支持 +clipboard)
"+p
6.3 Marks(书签)
#ma " 在当前位置设置书签 a(小写=文件内,大写=全局)
'a " 跳转到书签 a 所在行的行首
`a " 跳转到书签 a 的精确位置
:marks " 查看所有书签
" 特殊书签
`. " 最后修改的位置
`" " 上次退出时光标位置
`[ " 上次修改的起始位置
`] " 上次修改的结束位置
'' " 上次跳转前的位置
6.4 折叠
#zf{motion} " 手动创建折叠(如 zf5j 折叠下5行)
zo " 打开折叠
zc " 关闭折叠
za " 切换折叠状态
zR " 打开所有折叠
zM " 关闭所有折叠
zd " 删除当前折叠
" .vimrc 中设置折叠方式
set foldmethod=indent " 按缩进折叠(Python 友好)
set foldmethod=syntax " 按语法折叠
set foldmethod=marker " 按标记折叠({{{ 和 }}})
七、运维工程师高频场景
#7.1 批量删除空行
#" 方法1:全局命令
:g/^$/d
" 方法2:替换(将多个连续空行压缩成一个)
:%s/\n\{2,}/\r\r/g
" 方法3:只删除真正的空行(含空格的行也要删)
:g/^\s*$/d
7.2 注释多行
#" 方法1:Visual Block 模式(推荐)
Ctrl+v " 进入列选择模式
{j/k 选择行}
I " 大写 I,行首插入
# " 输入注释符
Esc " 退出,所有选中行自动添加 #
" 取消注释(Visual Block 选中 # 后 x 删除)
Ctrl+v
{j/k 选择行}
{选中注释符列}
d " 删除选中字符
" 方法2:替换命令
:5,20s/^/# / " 第5-20行行首添加 #
:5,20s/^# // " 第5-20行删除行首 #
7.3 列操作(Visual Block)
#" 场景:批量在某列插入内容
Ctrl+v " 进入 Visual Block
{选择行列范围}
I " 在选中块左侧插入
{输入内容}
Esc " 所有选中行同步插入
" 场景:批量替换某列字符
Ctrl+v
{选择区域}
r{新字符} " 替换为新字符
" 场景:选择矩形区域后执行替换
Ctrl+v
{选择}
:s/old/new/g " 只在选中区域内替换
7.4 读取命令输出
#:r !date " 将 date 命令输出插入到当前行下方
:r !cat /etc/hosts " 将文件内容插入
:r !ls -la " 将目录列表插入
" 对选中文本执行 shell 命令(结果替换选中内容)
{选择文本}
!sort " 对选中行排序
!awk '{print $2}' " 只保留第2列
7.5 快速编辑 config 文件
#" 删除所有注释行和空行(清理配置文件)
:g/^\s*#/d
:g/^\s*$/d
" 查找未注释的配置项
/^\s*[^#]
" 在多处做相同修改(使用 . 重复)
/MaxConnections
cwMaxConnections " 修改第一处
n " 跳到下一处
. " 重复修改
" 提取所有配置值(不含注释行)
:g!/^\s*#/p
7.6 比较两个文件
## 命令行启动 vimdiff
vimdiff file1 file2
vim -d file1 file2
# vimdiff 操作
# ]c 跳到下一个差异
# [c 跳到上一个差异
# do 从另一个文件获取差异(diff obtain)
# dp 将差异推送到另一个文件(diff put)
八、推荐 .vimrc 配置
#" ~/.vimrc
" === 基础配置 ===
set nocompatible " 关闭 vi 兼容模式
syntax on " 开启语法高亮
set number " 显示行号
set relativenumber " 相对行号(配合 hjkl 更高效)
set cursorline " 高亮当前行
set showcmd " 显示未完成命令
set wildmenu " 命令行补全菜单
set laststatus=2 " 始终显示状态栏
" === 缩进 ===
set tabstop=4 " Tab 显示为4个空格
set shiftwidth=4 " 自动缩进宽度
set expandtab " Tab 展开为空格
set smartindent " 智能缩进
set autoindent " 自动缩进
" === 搜索 ===
set incsearch " 增量搜索(边输入边高亮)
set hlsearch " 搜索结果高亮
set ignorecase " 搜索忽略大小写
set smartcase " 有大写字母时区分大小写
nnoremap <Esc><Esc> :nohlsearch<CR> " 双 Esc 清除高亮
" === 编辑体验 ===
set backspace=indent,eol,start " 退格键正常工作
set scrolloff=5 " 光标距屏幕边缘保持5行
set wrap " 长行自动折行
set linebreak " 在词边界折行
set history=200 " 命令历史数量
set undolevels=500 " 撤销步数
" === 文件处理 ===
set encoding=utf-8
set fileformats=unix,dos " 文件格式优先 unix
set nobackup " 不产生 ~ 备份文件
set noswapfile " 不产生 swp 文件(运维常见问题源)
" === 运维相关 ===
" 自动去除行尾空白
autocmd BufWritePre * :%s/\s\+$//e
" 显示不可见字符
set list
set listchars=tab:→\ ,trail:·,eol:¶
" 状态栏显示文件信息
set statusline=%F%m%r%h%w\ [%Y]\ [%{&ff}]\ [%l/%L:%c]
" === 快捷键映射 ===
let mapleader = "," " 前缀键设为逗号
" 快速保存
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<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
" 行移动(Visual 模式下上下移动选中行)
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
" 快速编辑 vimrc
nnoremap <leader>ev :e ~/.vimrc<CR>
nnoremap <leader>sv :source ~/.vimrc<CR>
九、常用命令速查表
#保存与退出
#| 命令 | 含义 |
|---|
:w | 保存 |
:w filename | 另存为 |
:q | 退出(有修改则报错) |
:q! | 强制退出(放弃修改) |
:wq | 保存并退出 |
:x | 有修改则保存后退出 |
ZZ | 同 :x |
ZQ | 同 :q! |
行号操作
#| 命令 | 含义 |
|---|
:set nu | 显示行号 |
:set nonu | 隐藏行号 |
:{n} | 跳到第 n 行 |
:. | 当前行号 |
:$ | 最后一行行号 |
常用 Ex 命令
#:!command " 执行 shell 命令
:shell " 临时进入 shell(exit 返回)
:pwd " 显示当前工作目录
:cd /path " 切换工作目录
:sort " 对选中行排序
:sort! " 逆序排序
:sort u " 排序并去重
:%!python3 -m json.tool " 格式化 JSON(用外部命令处理当前文件)