Vim 对于每个开发人员都不陌生,这可能是我们接触最多的 Linux 软件。所有类 Unix 的系统(Linux、Mac)都安装了 vim。当我们通过终端操作文本时,vim 或许是我们唯一的选择。
然而,vim 的使用方式和我们所熟悉的可视化编辑器完全不同,它的的快捷键是如此奇怪,不易上手。因此除非兴趣使然,我们很少会主动学习 vim。它的上限够高,下限也足够低,只需要掌握最基本的操作:↑↓←→、i、<ESC>、:wq,就可以覆盖大部分使用场景。那为什么还需要再深入学习 vim 呢?
主要原因是:用较少的学习成本,换来较大的效率提升。Vim 常用的几个快捷键,可以在手指不离开键盘热区的情况下快速定位光标或编辑内容,这些内容的学习成本并不高。如果你开发运维的过程中和 vim 打交道的次数越来越多,掌握这些技巧可以极大的提升开发效率。即使现在没有需求,也可以提前上手这个强大的工具。
为什么写这篇文章
现有的 vim 教程 / 文章大多直接罗列完整的 vim 快捷键列表,让人不知从何下手。我认为应当先掌握最重要的、最高频的快捷键,满足日常开发所需;其他低频使用的快捷键,可以作为一个速查表按需查看,vim 的进阶用法也可以之后再深入研究。
因此,我尝试作为一个 vim 初学者,总结 vim 主要和次要的快捷键,同时提供一些学习 vim 的资源。
注意:在阅读本文时,你随时可以在终端执行 vimtutor,打开一个教程文本文件,尝试某个快捷键或命令。
学习资源
- Missing Semester - 3. Vim 编辑器:非常推荐的课程,所有内容都很有帮助
- Mastering Vim:讲解 vim 里的“编程语言范式”,整体理解 vim
- The Vim Tutorial Part One - Youtube, Part Two:看英文字幕比较吃力的话,可以直接看本文
- vimtutor:安装 vim 后自带的教程,在终端执行
vimtutor即可打开,mac 系统下是中文文档 - Vim Adventure:以游戏的方式学习 vim
这里顺便再推荐一些可视化学习资源:
- 数据结构与算法:Data Structure Visualization、Visualgo
- 正则表达式:regexper
- Git:Learn Git Branching(强烈推荐)、Visualizing Git
术语说明
vim 中有一些术语:
- mode:标准模式 normal、插入模式 insert、可视模式 visual 等。
- verb:vim 里执行的操作,比如删除
d、修改c、拷贝y、查找f等。verb 后面需要跟一个 motion,表示该操作生效的范围。 - motion:vim 里移动的范围,比如向右一个字母
l、向下一行j、向右一个单词w等。本文中有时候也称其为 “range”。
符号说明
标题的前缀:
[M]:移动类,move[E]:编辑类,edit[F]:查找类,find
入门
标准模式 / 插入模式
- 标准模式(Normal Mode):进入 vim 的默认模式,这个模式下按下任何键不会实际输入到文本中,按下
:可以执行命令 - 插入模式(Insert Mode):在标准模式按下
i进入插入模式,此时可以输入文本;按下<ESC>退出插入模式
执行命令::<command>
按下 : 后输入命令,按回车执行。如 :set number 会显示行号。
退出 vim::q / ZZ
:q/:quit:退出 vim,不作任何改动:q!:退出 vim,丢弃已有的改动:wq:保存更改(write)并退出(quit)vimZZ:等同于:wq,这个快捷键输入比:wq更快,注意是大写Z
保存文件: :w / :w <filename>
:w:保存更改:w <filename>:保存到一个新的文件
[M] 基本移动:h / j / k / l
使用 h、j、k、l 而不是 ←、↓、→、↑,这能够避免将手指移出键盘热区再移回来。如果有必要的话,甚至可以禁用方向键,来强制自己使用 h、j、k、l:
1 | map <Left> <Nop> |
[M] 前往第一行 / 最后一行:gg / G
gg:前往第一行1G:同ggG:前往最后一行
[M] 前往第 n 行:nG、:n
nG:前往第 n 行。1G可以前往第一行。如果希望在 vim 中显示行号,可以在标准模式下执行set number命令。:n也可以前往第 n 行,比如:123前往第 123 行。
[M] 向右移动一个单词:w / e
w:向右移动一个单词,光标将落在下一个单词的首字符e:向右移动一个单词,光标将落在当前一个单词的最后一个字符
在这里,一个单词的定义是连续的「数字+字母+下划线」,或者连续的「特殊字符」。比如 hello, world!!! 里包含 hello、,、world 和 !!! 四个单词。按 w 跳转时,会跳过单词后面的所有空白字符,落在下一个单词的开头。示例:
1 | ↓ 光标在这里 |
类似的还有 W / E,区别在于这两个快捷键对单词的定义是连续的「非空字符」,即以空格作为单词的分界线。比如 hello, world!!! 里,包含 hello, 和 world!!! 两个单词。
[M] 向左移动一个单词:b
b 向左移动到前一个单词的首字符,相当于是 w 的逆操作。b 取 backwards 首字母,「单词」的定义同 w。
2b 向左移动两个单词,nb 向左移动 n 个单词。
B 向左移动一个单词,将「空格」作为单词的分隔符(同 W、E)。
[M] 移动到前一个单词的末尾:ge
ge 移动到前一个单词的末尾,gE 将空格作为单词的分隔符。
[M] 前往当前行第一个 / 最后一个字符:0 / $ / _ / ^
0:前往第一个字符,可以理解成是第 0 列$:前往最后一个字符_:前往第一个非空字符,这在编写 python 等有缩进的代码时很有用。^等价。
[E] 删除字符:x / X
x:删除当前字符,等同于<Delete>X:删除前一个字符
[E] 删除单词:dw
「单词」的定义同 w,单词后面的任意多个空格将被删除。
类似的还有 dW,删除下一个空格前的单词。
[E] 删除当前行:dd
略。
[E] 在当前位置后面插入:a
i 在当前位置前面插入(insert),a 在当前位置后面插入(append)。
[E] 在当前行开始 / 末尾插入:I / A
略。
[E] 在当前行下面 / 上面插入新行:o / O
插入新的空白行。
[E] 改变大小写:~ / gu / gU
~:将光标下的字母改变大小写。3~是将光标开始的 3 个字母改变大小写。gu<motion>:指定范围的字母变成小写。比如guw是后一个单词全变成小写,guj是当前整行改成小写。gU则是改成大写。guu:将当前行的字母改成小写。gUU是改成大写。guiw:将光标所在的单词改成小写。详见下文
[F] 移动到下一个指定字符:f<target>
ft 移动到下一个 t 出现的位置,f2 移动到下一个 2 出现的位置。f 取 forward 的首字母。
F 类似于 f,向前移动到前一个指定字符。
t 类似于 f,只不过光标会移动到下一个指定字符之前;T 类似于 F,只不过光标会移动到前一个指定字符之后。t 取 until 的含义。
示例:
1 | ↓ 光标在这里 |
[E] 撤销 / 重做:u / <Ctrl> + r
u:撤销(undo)<Ctrl> + r:重做(redo)
中场休息:vim 的一些模式
重复 n 次操作:n<action>
Vim 中几乎所有操作都可以通过一个 n 前缀来重复 n 次:
5h向左移动 5 个字符。5j向下移动 5 行。2w向右移动两个单词,等同于按两次w。2x删除两个字符,2X向左删除两个字符。3fa在当前行查找第 3 次出现的a,等同于按 3 次fa。2u撤销前两步操作,等同于按两次u。2<Ctrl> + r重做被撤销的两步操作,等同于按两次<Ctrl> + r。
操作任意范围:<verb><motion>
我们以 d 命令为例。d 可以和任意光标移动的操作结合,来删除一个范围的内容。
比如:w 是跳到下一个单词的开头,那么 dw 就是删除到下一个单词的开头;b 是跳转到前一个单词的开头,那么 db 就是删除到前一个单词的开头。以此类推,d0 是删除当前位置到行开头的所有内容,dG 是删除当前行到文件末尾的所有内容,dgg 是删除当前行到文件开头的所有内容。
大部分命令都支持 <verb><n><motion> 和 <n><verb><motion> 两种模式,比如 d2w 和 2dw 都是删除后两个单词。但在语义上有区别:d2w 表示删除 2w 范围的内容,而 2dw 表示 dw 命令重复 2 次。
命令的小写和大写:d / D 等
不同的方向:
x向右、X向左p向下、P向上o向下、O向上f向右、F向左
更严格的条件:
w将特殊字符作为独立单词,W只将空格作为单词分隔符e/E、b/B同理
更大的范围:
a在当前位置后面插入、A在当前行末尾插入i在当前位置前插入、I在当前行开始插入d删除一个范围、D删除到行末尾c删除一个范围、C删除到行末尾,并进入编辑模式s删除当前字符,并进入编辑模式;S删除当前整行,并进入编辑模式
连续操作:
r替换一个字符、R连续替换多个字符直到按下<Esc>
两个字母重复:dd / cc / yy / guu
两个 verb 字母重复,表示对当前整行操作:
dd:删除整行cc:删除整行,并进入编辑模式yy:复制整行guu:当前整行变成小写gUU:当前整行变成大写
重复上次操作:. / , / ;
.:重复上次的编辑操作。比如执行了A123<Esc>在当前行尾插入123后,可以移动到下一行,按.在该行末尾插入123。,/;:重复当前行内的上一次 / 下一次f查找。比如在当前行按fa找到第一个a字符后,按;可以查找下一个,等价于再按fa。按,是查找上一个,等价于Fa。n/N:按/bar<Enter>搜索bar字符串后,按n可以查找下一个,按N查找上一个。
进阶
[E] 替换一个字符:r
r:再按下任意键,替换(replace)当前字符,等同于 x + i。示例:
1 | ↓ 光标在这里 |
[E] 替换连续多个字符:R
R:替换连续的多个字符,按下 <Esc> 可以退出替换模式。
[E] 更改一个范围的内容:c
c 取 change 的首字母,这个命令的便捷之处在于将「删除操作」和「进入编辑模式」合二为一,可以少按一个键。
cw:更改下一个单词,等同于dw+ic2w:更改后两个单词,等同于d2w+ic$:更改从当前位置到行结束的所有内容,等同于d$+i
和 d 一样,c 也可以和任意光标移动的操作符结合,来更改一个范围的内容。
[E] 删除当前字符,并进入编辑模式:s
s 等同于 x + i。
[E] 删除当前整行,并进入编辑模式:S / cc
S 等同于 dd + o。cc 也可以删除整行,并进入编辑模式。
[E] 从当前位置开始向右删除整行:D
D 等同于 d$。
[E] 从当前位置开始向右删除整行,并进入编辑模式:C
C 等同于 c$,或者 d$ + a,或者 D + a。
[V] 可视模式选择内容:v / V / <Ctrl> + v
按下 v 进入可视模式(visual mode),然后移动光标以选择文本。可以针对选中的文本执行任意操作 (verb),比如:
- 按下
y可以复制选中的文本,再移动到别的位置按下p粘贴这些文本 - 按下
d可以删除选中的文本
按下 ctrl + v 可以进入 Visual Block Mode,选择一个矩形块里的内容:
按下大写 V 可以选中整行。常见的使用技巧:
- 按
V选中整行,按j向下选中多行,然后y复制。 - 按
V选中整行,按j向下选中多行,按<向左缩进,按.继续缩进。 - 按
V选中整行,按j向下选中多行,按=格式化。
复制下一个单词:yw
y 取 yank(复制)的首字母。yw 复制下一个单词,p 可以将其粘贴(put)到指定位置。
事实上,y 和 c、d 一样,可以和任意光标移动的操作符结合,来复制一个范围的内容。比如 y$ 将复制当前位置到行末尾的全部内容,yh 将复制光标前面的字符,yG 复制光标所在行到最后一行的所有内容。
最后,yy 复制当前行,可以和 dd 一起理解 —— dd 删除一整行,快捷键重复表示操作的是一整行,不管光标位置在哪里。第二个 y 和 d 并没有语义上的含义。
复制当前行:yy / 2yy / y2j
yy 复制当前行,p 粘贴到目标位置。
nyy 复制当前行往下的 n 行,包括当前行。
ynj 也是复制当前行往下的 n 行。比如 y2j 会复制当前行和下一行。
粘贴到下一行 / 上一行:p / P
如上所述,p 粘贴到目标位置。
通过 dd 删除某一行后,也可以按下 p,将删除掉的内容放置到当前光标位置下一行。注意这里是「放置」而不是「粘贴」,因为 dd 将被删除的行保存到了缓冲区,而 p 其实是将缓冲区的内容放置到当前位置,所以 p 取 put 的首字母,而非 paste。
同理,yy 将当前行保存到缓冲区,但不删除。这样 yy + p 就可以实现“复制-粘贴”的操作。
大写 P 粘贴到上一行。
当前行置顶:zt / zb / zz
zt 把当前行置于屏幕顶端。z 字取其象形意义,模拟一张纸的折叠变形。t 取 top 的首字母。
zz 将当前行置于屏幕中央。zb 将当前行置于屏幕底端,b 取 bottom 的首字母。
缩进:< / >
选中文本后,< 是向左缩进,> 是向右缩进。
格式化:=
按 = 可以将选中的文本格式化。这个命令可以配合 V 使用 —— 通过 V 选中多行,然后按 = 格式化选中的文本。
其他工具 Vim 化
Chrome
Vimium,通过类似 vim 风格的命令操作浏览器窗口。
VS Code
Vim 插件,将 VS Code 的编辑器转为 vim 模式。最近高频使用,V、ciw、di{ 等命令显著提升了编码效率。
编辑 settings.json 文件,配置 jj 替换 ESC:
1 | "vim.insertModeKeyBindings": [ |
终端 / Bash / zsh
在终端输入 set -o vi 可以切换到 vim 模式,按下 ESC 就能进入 vim 的 normal mode,修改终端命令的时候很好用。推荐将其写入 .bashrc 或 .zshrc 等配置文件。
在 zsh 中,也可以通过快捷键 Ctrl + x, Ctrl + e 打开 vim 编辑当前命令。
总结
掌握「入门」一节中的快捷键,基本可以满足大部分使用场景。如果想进一步提升效率,那么「进阶」一节中的快捷键也值得学习。
可以在其他编辑器中配合 vim 插件,来培养 vim 的使用习惯。
最后,在实践中学习命令!如果只是阅读而不尝试,那么很快就会遗忘。
希望本文对你有帮助。