07 绕不过的坎儿 - VIM 文本编辑器
为什么要学 Vi/VIM
- Linux 系统一切皆文件,文件编辑必不可少
- Vi 是大多数发行版系统自带的文本编辑器,在任何场景下都可以使用
- 无网络连接->无法远程登录
- 无桌面系统->无法使用鼠标
- 磁盘容量小->无法安装其他编辑器
Vi
- 历史:
Vi是 Visual Interface 的缩写,最初由 Bill Joy 在 1976 年为 BSD Unix 编写。 - 功能:
Vi是一个模式化的文本编辑器,它有三种基本模式:命令模式(Command mode)、插入模式(Insert mode)和末行模式(Last line mode)。 - 特性:
Vi的功能比较基础,适合进行快速的文本编辑任务。 - 可用性:因为
Vi是 Unix 系统的一部分,所以几乎所有的 Unix 和 Linux 发行版都会预装Vi。 - 扩展性:
Vi本身不支持插件。
VIM
- 历史:
VIM是vi IMproved的缩写,由 Bram Moolenaar 在 1991 年基于vi开发。 - 功能:
VIM不仅包含了vi的所有功能,还增加了许多新特性,如多级撤销、语法高亮、命令行历史、在线帮助、文件名补全、块操作等。 - 特性:
VIM非常强大,支持多种编程语言的语法高亮和代码折叠,还有大量的插件可以增强其功能。 - 可用性:虽然
VIM不是所有 Unix 和 Linux 发行版的默认编辑器,但它通常可以通过包管理器轻松安装。 - 扩展性:
VIM支持插件,这使得它的功能可以通过社区开发的插件极大地扩展。
Vi 和 VIM 的区别
- 部分发行版预安装
Vi,但是未安装VIM VIM是Vi的升级版,两者基础指令无差别区别
功能和扩展性
- Vi 是最初的版本,是 Unix 系统中的一个标准编辑器。它比较简单,功能有限,主要用于基本的文本编辑任务。
- VIM 是
Vi的增强版,它保留了Vi的所有功能,并增加了大量新功能和改进。VIM支持语法高亮、多级撤销、多窗口编辑、代码折叠、插件支持等特性,使得它更适合于复杂的开发和编辑任务。
用户界面
- Vi 和 VIM 在基本操作上非常相似,都是基于命令行界面的编辑器。它们没有图形用户界面(GUI),而是通过键盘命令来进行操作。
- VIM 相对于 Vi 在用户体验上有一些改进,例如更友好的错误提示、更多的定制选项和键绑定。
兼容性
- VIM 可以说是 Vi 的超集,几乎可以完全替代 Vi。VIM 保留了 Vi 的所有基本命令和操作方式,同时增加了许多新功能,因此在兼容性上,几乎所有 Vi 能够处理的任务,VIM 都可以胜任。
发展和社区
- Vi是由 Bill Joy 在 1976 年开发的,它作为 Unix 系统的一部分,因其简洁和高效而广受欢迎。
- VIM则由 Bram Moolenaar 在 1991 年开发,他增加了大量新特性,并积极维护和更新 VIM,使其成为当今最流行的文本编辑器之一。VIM 有一个活跃的社区支持和大量的插件生态系统。
VIM 的三种模式
- 命令模式(Command mode):控制光标移动,可对文本进行复制、粘贴、删除和查找等工作。
- 输入模式(Insert mode):正常的文本录入。
- 末行模式(Last line mode):保存或退出文档,以及设置编辑环境。

- 在每次运行 VIM 编辑器时(执行
vim [file]命令后),默认进入命令模式,此时需要先切换到输入模式后再进行文档编写工作。 - 而每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或退出操作。
- 在 VIM 中,无法直接从输入模式切换到末行模式。
命令模式
- 命令模式是 VIM 的默认模式,当你启动 VIM 或者从其他模式(如插入模式)退出时,编辑器会进入命令模式。
- 在命令模式中,用户可以使用各种键盘命令来操作文本,如导航、文本操作、剪切、复制、粘贴、查找和替换等。
- 常用的光标移动命令包括:
h/j/k/l(分别表示向左、向下、向上和向右移动光标)、w/b(分别表示移动到下一个单词的开头和上一个单词的开头)、e(移动到当前单词的末尾)等。 - 常用的文本编辑命令包括:
dd(删除光标所在行)、5dd(删除从光标处开始的 5 行)、yy(复制光标所在行)、5yy(复制从光标处开始的 5 行)、p(粘贴之前复制的文本)等。
- 常用的光标移动命令包括:
进入和退出命令模式
- 进入命令模式:启动 VIM 时默认进入命令模式。如果当前在其他模式(如插入模式),按
Esc键返回命令模式。 - 退出命令模式:在命令模式中,用户也可以通过输入特定的命令来切换到其他模式。
- 输入
a/i/o键切换到输入模式。 - 输入
:键切换到末行模式。
- 输入
命令模式常用命令
| 命令 | 作用 |
|---|---|
dd | 删除(剪切)光标所在整行 |
5dd | 删除(剪切)从光标处开始的 5 行 |
dw | 删除(剪切)光标所在位置到单词末尾的字符 |
x | 删除(剪切)光标所在位置的字符 |
u | 撤销上一步的操作 |
y | 复制选中内容 |
yy | 复制光标所在整行 |
5yy | 复制从光标处开始的 5 行 |
n | 显示搜索命令定位到的下一个字符串 |
N | 显示搜索命令定位到的上一个字符串 |
u | 撤销上一步的操作 |
p | 将之前删除(dd)或复制(yy)过的数据粘贴到光标后面 |
光标移动
| 命令 | 作用 |
|---|---|
h/l | 向左/向右移动一个字符 |
j/k | 向下/向上移动一行 |
w/b(word) | 移动到下一个/上一个单词的开头 |
e | 移动到当前单词的末尾 |
W/B、E | 与w/b、e类似,但它们以空白字符作为单词的分隔符 |
0/$(Home/End) | 移动到行首/行尾 |
^ | 移动到行首的第一个非空白字符 |
gg/G | 跳转到文件的第一行/最后一行 |
nG | 跳转到第 n 行 |
H/M/L | 移动到屏幕的顶部/中间/底部 |
文本修改
| 命令 | 作用 |
|---|---|
x/X | 删除光标下的字符/光标前的字符 |
d(delete) | 开始删除(剪切)操作,通常与移动命令结合使用,例如 d2w 删除两个单词,dd/D 删除一行,d$ 删除到行尾,2dd 删除从光标处开始的 2 行 |
c(copy) | 开始修改操作,与 d 类似,但会在删除后进入插入模式,例如 c2w 修改两个单词,cc/C 修改一行 |
s(search) | 替换光标下的字符,并进入插入模式 |
S | 替换光标所在的整行,并进入插入模式 |
r(replace) | 替换光标下的字符,不进入插入模式 |
R | 进入替换模式,可以连续替换多个字符 |
y(yank) | 开始复制操作(复制到文件缓冲区),通常与移动命令结合使用,例如 yw 复制一个单词,yy/Y 复制一行,y$ 复制到行尾,2yy 复制从光标处开始的 2 行 |
p/P(paste) | 在光标后/光标前粘贴复制或删除的内容 |
撤销与重做
| 命令 | 作用 |
|---|---|
u(undo) | 撤销最近的更改 |
Ctrl + r(redo) | 重做之前的撤销 |
搜索与替换
| 命令 | 作用 |
|---|---|
/pattern | 在文档中向下搜索匹配的文本 |
?pattern | 在文档中向上搜索匹配的文本 |
n | 跳转到下一个匹配项 |
N | 跳转到上一个匹配项 |
:%s/old/new/g | 在整个文档中替换所有出现的 old 为 new |
其他操作
| 命令 | 作用 |
|---|---|
. | 重复上一次的修改操作 |
> | 增加缩进 |
< | 减少缩进 |
zf | 创建折叠 |
zo | 打开折叠 |
zc | 关闭折叠 |
块编辑
| 命令 | 作用 |
|---|---|
v | 进入字符可视模式,可以移动光标选择文本 |
V | 进入行可视模式,可以移动光标选择行 |
Ctrl + v | 进入块可视模式,可以移动光标选择矩形块 |
I | 在选中的每一行开始插入模式 |
A | 在选中的每一行的末尾插入模式 |
d | 删除选中的文本 |
c | 修改选中的文本 |
y | 复制选中的文本 |
> | 增加选中的每一行的缩进 |
< | 减少选中的每一行的缩进 |
= | 自动对齐选中的每一行 |
:noh | 取消高亮显示的搜索结果 |
- 添加注释:先按下
Ctrl + v进入块可视模式,然后使用上下箭头键选择要添加注释的行,最后按下I进入插入模式,输入//,然后按下Esc键退出插入模式,注释就会被添加到选中的每一行前面。 - 删除注释:先按下
Ctrl + v进入块可视模式,然后使用上下箭头键选择要删除注释的行,最后按下d删除选中的文本,注释就会被删除。
插入模式
插入模式(Insert Mode)是一个允许你输入和编辑文本的模式。这是与命令模式(Normal Mode)最直接相对的模式,因为在插入模式中,你可以像在普通文本编辑器中那样输入字符。
| 命令 | 作用 |
|---|---|
i(insert) | 在光标前插入文本 |
a(append) | 在光标后插入文本 |
o(open a new line below) | 在光标下一行插入文本 |
I | 在当前行首插入文本 |
A | 在当前行尾插入文本 |
O(open a new line above) | 在光标上一行插入文本 |
gi | 回到上一次离开插入模式的位置并进入插入模式 |
gI | 在当前行的开头插入文本,忽略缩进 |
| 命令 | 说明 |
|---|---|
i、I | i是从光标所在位置开始输入,I是光标所在行第一个非空白字符开始输入 |
a、A | a是从光标所在的下一个字符开始输入,A是从光标所在行的最后一个字符开始输入 |
o、O | o是从光标所在行的下一行新的一行开始输入,O是从光标所在行的上一行新的一行开始输入 |
r、R | r是取代光标所在的字符一次,R是依次取代光标所在字符 |
插入模式的基本操作
进入插入模式后,可以进行以下操作:
- 输入字符:直接输入文本字符。
- 输入特殊字符:
<Ctrl-V>后跟一个字符:插入该字符的字面值。<Ctrl-R>后跟寄存器名称:插入寄存器中的内容。<Ctrl-O>后跟命令模式命令:暂时回到命令模式执行一个命令,然后返回插入模式。
在插入模式中的光标移动
在插入模式中,常规的光标移动方式(如 h, j, k, l)将插入这些字符,而不是移动光标。然而,你可以使用以下组合键来移动光标:
| KEY | 作用 |
|---|---|
<Ctrl-A> | 光标移动到行首 |
<Ctrl-E> | 光标移动到行尾 |
<Ctrl-F> | 光标向前移动一个字符 |
<Ctrl-B> | 光标向后移动一个字符 |
<Ctrl-N> | 光标向下移动一行 |
<Ctrl-P> | 光标向上移动一行 |
<Ctrl-D> | 光标向下移动半页 |
<Ctrl-U> | 光标向上移动半页 |
<Ctrl-H>:删除光标前的一个字符(同退格键)。<Ctrl-W>:删除光标前的一个单词。<Ctrl-U>:删除光标前的整行。<Ctrl-D>:减少自动缩进。<Ctrl-T>:增加自动缩进。<Left>:左移光标。<Right>:右移光标。<Up>:上移光标。<Down>:下移光标。
退出插入模式的方法
Esc:退出插入模式,回到命令模式。<Ctrl-[>:功能与Esc相同,退出插入模式。<Ctrl-C>:功能与Esc相同,退出插入模式。
使用插入模式的一些技巧
- 自动完成:在插入模式中输入部分单词后,按
<Ctrl-N>或<Ctrl-P>进行自动补全。 - 多行插入:在命令模式下,选择多行(例如
V然后移动光标选择多行),按I进入插入模式并输入内容,然后按Esc,输入的内容将插入到每一行的开头。 - 快速注释:在命令模式下,选择多行并输入
:,然后输入'<,'>s/^/#/将在每行开头插入#,使其变成注释。
插入模式中的插入命令
在插入模式中,有许多有用的命令可以帮助你更高效地编辑文本:
<Ctrl-E>:将插入点向下移动一行,但不离开插入模式。<Ctrl-Y>:将插入点向上移动一行,但不离开插入模式。<Ctrl-N>:自动完成单词(向下)。<Ctrl-P>:自动完成单词(向上)。
插入模式中的高级操作
- 录制和使用宏:在命令模式下按
q然后选择一个寄存器(如a),进入插入模式进行操作,按q结束录制。然后在命令模式下按@a可以重复执行该宏。 - 粘贴模式:有时你需要从外部粘贴大量文本到 VIM 中,可以使用
:set paste进入粘贴模式,然后按i进入插入模式并粘贴。结束后使用:set nopaste返回正常模式。
末行模式
末行模式(也称为命令行模式或 Ex 模式)是一种强大的模式,用于执行各种命令,如文件保存、退出、查找和替换、设置选项等。进入末行模式后,您可以在 VIM 窗口底部的命令行输入命令。
进入末行模式
在命令模式(Normal Mode)下,按下 : 键即可进入末行模式。光标将移动到窗口底部的命令行,等待输入命令。末行模式通常通过 :, / 和 ? 等符号进入:
::用于执行大多数 Ex 命令。/:用于向前查找。?:用于向后查找。
退出末行模式
按下 Esc 键可以退出末行模式并返回命令模式。
末行模式常用命令
| 命令 | 作用 |
|---|---|
:w | 保存 |
:q | 退出 |
:q! | 强制退出(放弃对文档的修改内容) |
:wq! | 强制保存退出 |
:set nu | 显示行号 |
:set nonu | 不显示行号 |
:命令 | 执行该命令 |
:整数 | 跳转到该行 |
:s/one/two | 将当前光标所在行的第一个one替换成two |
:s/one/two/g | 将当前光标所在行的所有one替换成two |
:%s/one/two/g | 将全文中的所有one替换成two |
?字符串 | 在文本中从下至上搜索该字符串 |
/字符串 | 在文本中从上至下搜索该字符串 |
文件操作
| 命令 | 作用 |
|---|---|
:w | 保存当前文件 |
:w! | 强制保存当前文件,即使文件权限不允许写入 |
:w filename | 将当前文件另存为指定的文件名 |
:q | 退出 VIM(如果有未保存的更改,将无法退出) |
:wq / :x / ZZ | 保存当前文件并退出 VIM |
:q! / ZQ | 不保存任何更改,强制退出 VIM |
:e filename | 打开指定的文件,如果当前文件有更改则提示保存 |
:n | 打开下一个文件(在 VIM 中使用多个文件缓冲区时) |
:prev / :N | 打开上一个文件(在 VIM 中使用多个文件缓冲区时) |
:r filename | 将指定文件的内容读入当前文件,插入到光标所在位置 |
编辑操作
| 命令 | 作用 |
|---|---|
:d | 删除当前行 |
:d {range} | 删除指定范围内的行,例如 :d 3,5 删除第 3 行到第 5 行 |
:y | 复制当前行 |
:y {range} | 复制指定范围内的行,例如 :y 3,5 复制第 3 行到第 5 行 |
:p | 在当前行后粘贴复制或删除的内容 |
:m {line} | 移动当前行到指定的行号,例如 :m 10 将当前行移动到第 10 行之后 |
查找和替换
| 命令 | 作用 |
|---|---|
/pattern | 在文件中向前搜索匹配的文本 |
?pattern | 在文件中向后搜索匹配的文本 |
:s/old/new | 将当前行中的第一个 old 字符串替换为 new 字符串 |
:s/old/new/g | 将当前行中的所有 old 字符串替换为 new 字符串 |
:%s/old/new/g | 将整个文件中的所有 old 字符串替换为 new 字符串 |
:%s/old/new/gc | 将整个文件中的所有 old 字符串替换为 new 字符串,并在每次替换前进行确认 |
行范围
.:表示当前行。$:表示最后一行。^:表示第一行。n:表示第n行。例如:n跳转到第 n 行。.,$和^等符号可以组合使用,例如::.,$d:删除从当前行到最后一行的所有行。:1,$y:复制整个文件的所有行。:2,10d:删除文件第 2 - 10 行。:.=~:显示当前行号
窗口操作
:split或:sp:水平分割窗口。:vsplit或:vsp:垂直分割窗口。:close:关闭当前窗口。:only:关闭除当前窗口外的所有窗口。
设置选项
:set option:设置选项。例如,:set number显示行号。:set nooption:关闭选项。例如,:set nonumber关闭行号。:set option=value:设置选项的值。例如,:set tabstop=4将 Tab 宽度设置为 4 个空格。常用设置选项
:set nu或:set number:显示行号。:set nonu或:set nonumber:关闭行号。:set hlsearch:开启搜索高亮。:set nohlsearch:关闭搜索高亮。:set ignorecase:搜索时忽略大小写。:set noignorecase:搜索时区分大小写。:set tabstop=4:设置 Tab 宽度为 4 个空格。:set expandtab:将 Tab 替换为空格。:set noexpandtab:使用实际的 Tab 字符。
自定义命令
可以使用 :command 自定义命令。例如:
bash
:command WQ wq这样,可以使用 :WQ 代替 :wq。
执行外部命令
:!command:执行外部 shell 命令。例如,:!ls列出当前目录的文件。
末行模式的组合使用
可以将多个命令组合在一起使用,例如:
bash
:1,10s/old/new/g | w这个命令将文件的第 1 行到第 10 行中的所有 old 替换为 new,然后保存文件。