Vim 命令大全:常用命令速查表与运维必会 20 条
Vim 命令大多在普通模式下执行,格式是“次数 + 操作 + 范围”:dd 删一行,3dd 删三行,dw 删到下一个词。下面按移动、插入、删除、复制粘贴、查找替换、保存退出分组列出,标 ★ 的 20 条足够完成日常改配置的工作。
Vim 命令分两类:一类是在普通模式下直接按的键,如 dd、yy、p;另一类是按冒号后在屏幕底行输入、回车执行的命令,如 :wq、:%s/旧/新/g。下面的速查表按用途分成六组,每条附一句说明,标 ★ 的 20 条是运维修改配置文件时用得最多的,先把它们练熟,其余的用到再查。除特别注明的以外,表中命令都在普通模式下执行;不确定当前处于哪个模式,先按 Esc。
先看懂组合规则:次数 + 操作 + 范围
Vim 的编辑命令大多可以拆成三段,理解了规则,很多命令不用死记:
| 组成部分 | 常见写法 | 说明 |
|---|---|---|
| 次数 | 3、10 |
写在最前面,表示重复几次,省略就是 1 次 |
| 操作符 | d 删除、c 修改、y 复制、> 右缩进、< 左缩进 |
单独按不会生效,等你给出范围 |
| 范围(移动) | w 下一个词首、e 词尾、$ 行尾、0 行首、G 文件末尾、gg 文件开头 |
所有移动光标的命令都能当范围用 |
| 范围(文本对象) | iw 一个词、i" 引号里面、i{ 花括号里面、ip 一段 |
光标在对象内任意位置都能用;i 不含边界,a 连边界一起 |
照这个规则组合:d$ 删到行尾,c0 改到行首,dG 从当前行删到文件末尾,y3w 复制三个词,di{ 清空一对花括号里的内容(改 nginx 的 server 块很顺手),ci" 改写引号里的内容。操作符连按两次表示作用于整行:dd、cc、yy、>>。还有一个省事的 .,它重复上一次修改:在一处把 # 删掉后,用 n 跳到下一个匹配,再按 . 就完成同样的修改。
移动光标
| 命令 | 说明 |
|---|---|
h j k l |
左、下、上、右,方向键也可以 |
w / b / e |
下一个词的开头、上一个词的开头、当前词的结尾 |
★ 0 / $ |
行首、行尾;^ 跳到行首第一个非空字符 |
★ gg / G |
文件第一行、最后一行 |
★ :行号 |
跳到指定行,如 :120;普通模式下输入 120G 效果相同 |
★ :set nu |
显示行号,:set nonu 关闭,配合按行号跳转和指定范围 |
Ctrl+f / Ctrl+b |
向下、向上翻一页 |
Ctrl+d / Ctrl+u |
向下、向上翻半页 |
H / M / L |
跳到当前屏幕的顶部、中间、底部 |
% |
在配对的 ()、[]、{} 之间来回跳 |
fx / ; |
跳到本行下一个字符 x,; 继续找下一个 |
g; |
回到上一次修改的位置 |
Ctrl+o / Ctrl+i |
回到跳转前的位置 / 再跳回来 |
插入、删除与撤销
进入插入模式
| 命令 | 说明 |
|---|---|
★ i |
在光标前插入 |
a |
在光标后插入 |
I |
在行首第一个非空字符前插入 |
★ A |
在行尾追加,给配置项补参数时常用 |
★ o |
在当前行下方新开一行并插入 |
O |
在当前行上方新开一行并插入 |
s |
删除光标处的字符后插入 |
S 或 cc |
清空当前行后插入 |
★ Esc |
回到普通模式,Ctrl+[ 效果相同 |
Ctrl+w(插入模式下) |
删除光标前的一个词 |
Ctrl+u(插入模式下) |
删除本行光标前输入的内容 |
删除、修改与撤销
| 命令 | 说明 |
|---|---|
★ x |
删除光标处的一个字符,去掉行首的注释符 # 就靠它 |
★ dd |
删除整行,5dd 删除 5 行;删掉的内容可以用 p 粘贴,相当于剪切 |
dw / D |
删除到下一个词首 / 删除到行尾(同 d$) |
dG / dgg |
删除到文件末尾 / 删除到文件开头 |
★ cw |
改写从光标到词尾的内容,改端口号、改参数值常用;光标要先放在词首,否则只改后半截 |
C |
改写从光标到行尾的内容 |
r + 字符 |
把光标处的一个字符替换掉,例如 r1 |
R |
进入替换模式,输入的内容逐个覆盖原字符 |
J |
把下一行接到当前行末尾 |
~ |
切换光标处字母的大小写 |
★ u |
撤销上一步,可以连续撤销 |
★ Ctrl+r |
重做被撤销的操作 |
. |
重复上一次修改 |
:e! |
放弃所有未保存的修改,从磁盘重新载入文件 |
复制与粘贴
| 命令 | 说明 |
|---|---|
★ yy |
复制当前行,3yy 复制 3 行 |
yw / y$ |
复制到下一个词首 / 复制到行尾 |
★ p / P |
粘贴到光标后 / 光标前;复制的是整行时,分别粘贴到下一行 / 上一行 |
v、V、Ctrl+v 后按 y |
按字符、按行、按列选中后复制 |
ddp |
当前行与下一行互换位置 |
"ayy / "ap |
复制到名为 a 的寄存器 / 从寄存器 a 粘贴,可以同时存好几段内容 |
:reg |
查看所有寄存器里的内容 |
:10,20t 30 |
把第 10 到 20 行复制到第 30 行下方 |
:10,20m 30 |
把第 10 到 20 行移动到第 30 行下方 |
从本机复制一段配置,在终端里粘贴进 Vim,有时每一行都比上一行多缩进一截,或者注释符号被自动带到下一行。这是 Vim 把粘贴当成了逐键输入,触发了自动缩进和自动注释。Vim 从 8.0.0210 补丁起支持“括号粘贴模式”(bracketed paste),在支持它的终端里能自动识别粘贴;版本较老、或者经由浏览器控制台把剪贴板内容模拟成键盘输入时(例如 IPMI 远程管理里的 VNC 控制台粘贴),仍可能出现,处理方法是:
:set paste
" 然后按 i 进入插入模式粘贴,完成后按 Esc
:set nopaste
查找与替换
| 命令 | 说明 |
|---|---|
★ /关键词 |
向下查找,回车后 n 跳到下一个、N 跳到上一个 |
?关键词 |
向上查找 |
* / # |
查找光标所在的这个词,向下 / 向上 |
:noh |
取消查找结果的高亮 |
/\<listen\> |
只匹配完整的词,不匹配 listener |
/^#\?Port |
查找以 Port 或 #Port 开头的行 |
★ :%s/旧/新/g |
全文替换,% 表示所有行,g 表示一行内的每一处 |
:%s/旧/新/gc |
全文替换,每一处先确认:y 替换、n 跳过、a 剩余全部替换、q 停止 |
:10,20s/旧/新/g |
只替换第 10 到 20 行 |
:'<,'>s/旧/新/g |
只替换可视模式选中的行,选中后按 : 会自动带出前缀 |
:%s#/var/www#/data/www#g |
内容里有 / 时,改用 # 作分隔符,免去逐个转义 |
:%s/\s\+$//e |
删除所有行尾空格,e 表示没找到时不报错 |
:g/关键词/d |
删除所有包含关键词的行 |
:v/关键词/d |
删除所有不包含关键词的行 |
Vim 的正则和 grep -E 不完全一样:+、?、|、() 默认要加反斜杠,写成 \+、\?、\|、\(\)。表达式复杂时在开头加 \v(very magic 模式),这些符号就可以直接写,例如 :%s/\v(\d+)\.(\d+)/\2.\1/g 把形如 1.2 的数字前后对调。
保存与退出
| 命令 | 说明 |
|---|---|
★ :w |
保存但不退出,改完先存一下,切到另一个终端里测试配置 |
★ :wq 或 :x |
保存并退出;:x 只在内容有改动时才写文件,不会白白更新修改时间 |
ZZ |
普通模式下的快捷键,同 :x |
★ :q! |
不保存,强制退出 |
ZQ |
普通模式下的快捷键,同 :q! |
:q |
退出;有未保存的修改时会被拒绝 |
:w 新文件名 |
另存一份,当前编辑的仍是原文件 |
:sav 新文件名 |
另存为,之后编辑的是新文件 |
:10,20w 片段.txt |
只把第 10 到 20 行写到另一个文件 |
:wa / :qa / :wqa |
打开多个文件或分屏时:全部保存 / 全部退出 / 全部保存并退出 |
运维常用组合
上面的命令组合起来,能解决改配置时的很多具体麻烦:
| 要做的事 | 操作 |
|---|---|
| 批量注释连续几行 | Ctrl+v 进入列选择,j 向下选中这几行的行首,按 I 输入 #,再按 Esc,每行都加上了 |
| 批量取消注释 | Ctrl+v 选中行首那一列 #,按 x 删除;也可以用 :20,30s/^#// |
| 只看配置里生效的行 | vim -R 只读打开,先执行 :g/^\s*#/d 删掉注释行,再执行 :g/^\s*$/d 删掉空行,看完 :q! 退出,原文件不受影响 |
脚本报 /bin/bash^M: bad interpreter |
文件在 Windows 上编辑过,行尾多了回车符。:set ff? 显示 fileformat=dos 时,执行 :set ff=unix 再 :wq |
| 中文显示乱码 | :e ++enc=gb18030 按 GB18030 重新打开;确认正常后 :set fenc=utf-8 再 :w,文件就转成了 UTF-8 |
| 看清 Tab 和行尾空格 | :set list,Tab 显示为 ^I,行尾显示 $;YAML 报缩进错误时先看这个 |
| 对比两份配置 | 在 shell 里执行 vimdiff a.conf b.conf,]c / [c 跳到下一处 / 上一处差异,do 取对方的内容,dp 把这边的内容推过去 |
| 同时打开多个文件 | :e 文件 切换编辑,:sp 文件 上下分屏,:vsp 文件 左右分屏,Ctrl+w w 在窗口间切换 |
| 插入命令的输出 | :r !date +%F 在下一行插入当天日期,写变更注释时用 |
几点提醒:批量注释用的列选择插入,要在按 Esc 之后才会同步到所有选中的行,输入时只看到第一行有变化是正常的;:g 和 :v 删除的范围大,执行前确认自己没有误开在需要保留的文件上,误删了马上按 u;改配置前先用 cp -a 备份一份,比任何撤销命令都可靠。
常见问题
怎么在 Vim 里执行 shell 命令而不退出?
普通模式下输入 :!命令,例如 :!nginx -t,看完结果按回车回到编辑界面;:r !命令 会把命令输出插入到光标下方,例如 :r !hostname -I。想临时回到终端做别的事,按 Ctrl+z 把 Vim 挂到后台,处理完输入 fg 回来。
这些命令在 vi、vim-tiny、BusyBox vi 里都能用吗?
移动、插入、删除、复制粘贴、查找、:s 替换和保存退出这些基础命令都能用。可视模式、多级撤销、分屏、文本对象属于 Vim 的扩展,精简版本里可能没有或不完整,遇到不认的命令就退回基础写法。
Vim 里复制的内容能粘贴到电脑上吗?
默认不能。yy、p 用的是 Vim 自己的寄存器,和操作系统的剪贴板不通;写入系统剪贴板要求 Vim 编译时带有 clipboard 功能并且有图形环境,通过 SSH 连接的服务器一般不满足。从 Vim 往外复制,直接用终端软件的鼠标选中复制即可。