跳转到内容

Vim

Vim 是一个高效的模态文本编辑器,通过区分不同的编辑模式,实现快速的文本操作,避免频繁使用鼠标和方向键。

Terminal window
vim [选项] [文件名]
参数 说明
文件名 要编辑的文件

Vim 采用模式编辑的理念,按键在不同模式下有不同的作用:

  • 普通模式:用于浏览文件,执行各种命令,如 dd、yy、p、u
  • 插入模式:用于输入文本,像普通编辑器一样打字
  • 替换模式:类似插入模式,但新字符会替换旧字符(逐个替换)
  • 可视模式:用于选择一段文本以进行操作(删除、复制、缩进等)
  • 命令模式:用于执行冒号命令,如 :w 保存、:s 查找替换等
  • 定义:当在 Vim 中打开一个文件时,Vim 就会为它在内存中创建一个缓冲区,并将文件从磁盘中读取到缓冲区中。Vim 的操作实际是在操作缓冲区,保存时才写回磁盘。
  • 特点:
    • 每个文件对应一个缓冲区
    • 即使缓冲区没有在窗口中显示,它依然存在于内存中
  • 相关命令:
    • :ls 或 :buffers:列出所有缓冲区
    • :b <num>:跳转到编号为 <num> 的缓冲区
    • :bd:删除当前的缓冲区
    • :bn / :bp:切换下一个 / 上一个缓冲区
  • 定义:Vim 的窗口是对缓冲区内容的一个“视图”,可以理解为“查看缓冲区的窗口”。在一个 Vim 实例中可以打开多个窗口,每个窗口可以显示同一个或不同的缓冲区。
  • 特点:
    • 一个窗口只能显示一个缓冲区,但一个缓冲区可以被多个窗口同时显示
    • 窗口可以被分割(水平 / 垂直),形成多个子窗口
  • 相关命令:
    • :split(或 :sp):水平分割窗口
    • :vsplit(或 :vsp):垂直分割窗口
    • <Ctrl-w> h/j/k/l:在窗口之间切换
    • :close:关闭当前窗口
    • :only:关闭其他窗口,只保留当前
  • 定义:标签页是窗口的集合。每个标签页可以包含一个或多个窗口,它们的布局是独立的,可以理解为“一组窗口的容器”。
  • 特点:
    • 每个标签页可以包含多个窗口,切换标签页时会整体切换窗口布局
    • 不同标签页之间互不干扰,可以作为“工作区”使用
  • 相关命令:
    • :tabnew:新建一个标签页
    • :tabs:列出所有标签页
    • :tabnext 或 gt:切换到下一个标签页
    • :tabprev 或 gT:切换到上一个标签页
    • :tabclose:关闭当前标签页
标签页
└── 窗口
└── 缓冲区
  • 一个标签页中可以有多个窗口
  • 一个窗口中显示一个缓冲区
  • 一个缓冲区可以在多个窗口中同时显示

寄存器就是 Vim 里的“剪贴板”,可以存放文本(复制、剪切、宏录制等内容),Vim 有多个寄存器,支持多份内容同时存储。

寄存器名 含义与用途 使用示例
"" 默认寄存器,存放最近一次 yank 或 delete p 粘贴默认寄存器内容
"0 yank 寄存器,只存放最近一次 yank(复制) "0p 粘贴最后复制内容
"+ 系统剪贴板寄存器(需要支持) "+y 复制到系统剪贴板
"- 黑洞寄存器,删除但不保存内容,避免污染其他寄存器 "_d 删除但不存寄存器
"1–"9 编号寄存器,存放删除操作的历史 "1p 粘贴最近删除的内容
"a–"z 命名寄存器,可手动存储和调用文本 "ayy 复制到寄存器 a
  • 查看寄存器内容
    :registers " 查看所有寄存器及其内容
    :reg a + 0 " 查看寄存器 a、+、0 的内容
  • 复制到指定寄存器
    "ayy " 把当前行复制到寄存器 a
  • 删除到指定寄存器
    "adw " 删除一个单词并保存到寄存器 a
    "_dd " 删除一行但不保存(黑洞寄存器)
  • 粘贴指定寄存器内容
    "ap " 将寄存器 a 的内容粘贴在光标后
  • 使用系统剪贴板
    "+y " 复制到系统剪贴板
    "+p " 从系统剪贴板粘贴

    要求 Vim 支持系统剪贴板,可用 :version 查看是否有 +clipboard。

vim模式切换.png

命令 用途
i 在光标前插入
a 在光标后插入
I 在当前行首插入
A 在当前行末插入
o 在当前行下方新开一行并插入
O 在当前行上方新开一行并插入
命令 用途
r 进入替换模式,只取代光标所在的那一个字符一次
R 进入替换模式,会一直取代光标所在的字符,直到按下 ESC 为止
命令 用途
v 进入字符选择可视模式
V 进入行选择可视模式
<Ctrl-v> 进入块选择(列选择)模式
命令 用途
: 执行命令(保存、退出、设置等)
/ 向前查找
? 向后查找
命令 用途
<Ctrl-f> 向下翻页
<Ctrl-b> 向上翻页

Motion 可以进行光标移动,其核心作用是在文本中指定一个范围,配合操作符(如 d、c、y 等)来操作这段文本。常用 motion:

命令 用途
h 光标向左移动一个字符
j 光标向下移动一个字符
k 光标向上移动一个字符
l 光标向右移动一个字符
0 光标移动到该行的行首,相当于 <Home>
$ 光标移动到该行的末尾,相当于 <End>
w 光标移动到下一个单词的开头
e 光标移动到当前/下一个单词的结尾
b 光标移动到前一个单词的开头
ge 光标移动到前一个单词的结尾
G 光标移动到文件的最后一行
gg 光标移动到文件的第一行
% 光标移动到匹配的括号
{ 移动到上一个段落开头
} 移动到下一个段落开头

其他移动指令:

命令 用途
<num> h/j/k/l 光标向左/下/上/右移动 num 行
<num><Enter> 光标向下移动 num 行
<num>G 光标移动到文件的第 <num> 行

Vim 中对文件进行删除、复制、变更等操作有一个统一的格式:

operator [number] motion
  • operator:表示要对选定文本执行的操作
    • d – 删除(delete)
    • y – 复制(yank)
    • c – 更改(change)
    • > – 右缩进
    • < – 左缩进
    • = – 自动缩进
  • number:可选的数字,表示重复操作的次数
  • motion:表示操作范围的移动方式

注意:2dw 和 d2w 效果相同,Vim 会把数字自动识别为作用于 motion 的重复。

删除操作

普通命令:

命令 用途
x 删除光标后的字符,相当于 <Delete>
X 删除光标前的字符,相当于 <Backspace>
<num>x/X 删除光标后/前连续 <num> 个字符
dd 删除光标所在整行(包括换行符),并放进剪贴板
<num>dd 删除光标所在的向下 <num> 行(包括换行符),并放进剪贴板

操作符命令:

命令 用途
dw 删除从当前光标位置到下一个单词开头之间的内容
de 删除从当前光标位置到当前或下一个单词末尾之间的内容
d$ 删除从当前光标位置到该行行尾之间的所有内容

复制操作

普通命令:

命令 用途
yy 复制光标所在那一行
<num>yy 复制光标所在的向下 num 行

操作符命令:

命令 用途
y$ 复制光标所在字符到该行行尾的所有文本
yG 复制光标所在行到文件最后一行的所有文本

变更操作

变更是指删除指定范围内容并进入插入模式。

普通命令:

命令 用途
cc 更改整行的文本(删除整行后进入插入模式)
C 更改光标至行尾的文本
s 更改光标所在的一个字符,并进入插入模式
S 更改整行的文本,等价于 cc

操作符命令:

命令 用途
c$ 更改到行尾
c0 更改到行首
c% 更改括号间的内容

粘贴文本的来源:最近一次 yank 或 delete。

命令 用途
p 将复制的文本粘贴到光标所在的下一行
P 将复制的文本粘贴到光标所在的上一行
命令 用途
>> 当前行向右缩进一次
<< 当前行向左缩进一次
n>> 将当前行及下面 n-1 行向右缩进
n<< 将当前行及下面 n-1 行向左缩进
命令 用途
u 撤销前一个动作(无论插入、删除、粘贴还是替换)
<Ctrl-r> 重做上一个动作(取消刚刚的撤销操作)
命令 用途
. 重复前一个动作
命令 用途
/<word> 向光标下寻找名称为 word 的字符串
?<word> 向光标上寻找名称为 word 的字符串
n 重复前一个搜索动作
N 反向进行前一个搜索动作

如果执行 /hello 去向下搜索 hello,则按下 n 后会向下继续搜索下一个 hello。如果是执行 ?hello,那么按下 n 后会向上继续搜索,按下 N 反向搜索。

搜索时不区分大小写的方法:

  • 搜索时加上 \c,即 /<word>\c,表示忽略大小写
  • 设置当前 Vim 会话忽略大小写::set ignorecase
  • 设置智能大小写敏感(搜索关键词都是小写则不区分大小写,包含大写字母则自动启用大小写敏感):
    :set ignorecase
    :set smartcase

    两个都要设置,缺一不可。

基本替换语法:

:[范围]s/原内容/新内容/[标志]
  • [范围]:指定替换所作用的范围,缺省默认当前行
    • % 表示整个文件
    • . 表示当前行
    • <n1>,<n2> 表示第 n1 行到第 n2 行
    • '<,'> 表示选区(进入可视模式后 Vim 会自动填入)
  • s:substitute
  • [标志]:控制其他行为
    • g:global,贪婪模式,替换范围内所有匹配项
    • c:confirm,每次替换前询问
    • i:ignorecase,本次替换忽略大小写
    • n:no-substitute,只查找匹配数,不进行真正替换

常用替换命令:

替换命令 说明
:s/foo/bar/ 当前行第一次出现的 foo 替换为 bar
:s/foo/bar/g 当前行所有 foo 替换为 bar
:s/foo/bar/gc 替换时每次都询问是否确认
:%s/foo/bar/g 替换整个文件中的所有 foo 为 bar
:3,10s/foo/bar/g 替换第 3 到第 10 行之间的内容
:'<,'>s/foo/bar/g 替换当前选中的可视区域
指令 说明
:w 保存当前文件(write)
:q 退出
:q! 强制退出(不保存)
:wq 或 :x 保存并退出
:e filename 打开指定文件
:r filename 读取并插入文件内容到当前光标下
:w filename 另存为指定文件名
:n1,n2 w filename 将 n1 到 n2 行的内容保存为指定文件名
指令 说明
:!command 执行 shell 命令(如 :!ls、:!gcc a.c)
:help {标题} 打开帮助文档(如 :help :w 打开 :w 命令的帮助文档)

基本格式:

:set 选项名 " 开启某个选项
:set no选项名 " 关闭某个选项
:set 选项=值 " 设置某个选项的具体值
:set 选项? " 查看当前设置值

常用环境变更指令:

命令 说明
:set number 显示行号
:set nonumber 取消行号
:set showcmd 在屏幕下方显示部分命令(如 d2w)
:set ruler 显示光标当前位置(行、列)
:set ignorecase 搜索时忽略大小写
:set incsearch 输入搜索时就高亮匹配项
:set hlsearch 搜索完成后高亮所有匹配
:nohlsearch 或 :noh 关闭搜索高亮

打开文件并跳转到指定行:

Terminal window
vim +100 myfile.c # 打开文件并跳到第 100 行

批量注释多行(块选择模式):

  1. <Ctrl-v> 进入块选择模式
  2. j 或 k 选择需要注释的行
  3. I 进入插入模式,输入 //
  4. 按 ESC,所有选中行均被注释

全局替换字符串:

:%s/oldword/newword/g