初识vim
一、Vim是什么
Vim是一个强大的模态文本编辑器,入门门槛较高,但是一旦掌握,编辑效率非常高。
Vim与普通编辑器最大的区别在于它有多种模式,同一个按键在不同模式下含义完全不同,理解这一点是入门的关键,也是很多人刚上手时觉得很麻烦的一点
1.1 Normal模式(普通模式)
打开Vim后默认进入的模式。这个模式下,键盘上的字母不是用来输入文字的,而是用来执行命令的。比如按d是删除(delete),按y是复制(yank),按p是粘贴(paste)。这是Vim里待得最久的模式,浏览代码、跳转、删除、复制都在这里完成。
从其他任何模式回到Normal模式:按Esc键,这是Vim里按的最频繁的键,很多大佬会把Caps Lock键映射成Esc以提升效率。
1.2 Insert模式(插入模式)
这是真正用来输入文字的模式。从Normal模式进入Insert模式有多种方式,后面详细讲解
1.3 Visual模式(可视模式)
用来选中文本块。选中后可以执行删除、复制、缩进等操作。Vim有三种Visual子模式:字符选中v、行选中V、块选中Ctrl+v
1.4 Command-line模式(命令行模式)
在Normal模式下按:进入,可以执行保存、推出、搜索替换等命令。
二、为什么要用Vim
在VS Code、JetBrains系列如日中天的今天,为什么还要花时间学一个并不简单的30年的老编辑器呢?
- 编辑效率的提升:
- 现代编辑器有漂亮的界面、智能补全、鼠标点选等功能,可以大幅提升我们的编辑体验和效率,但它们都有一个共同的瓶颈——编辑文本时手需要频繁的在键盘和鼠标之间切换,容易打断思路。
- Vim的哲学时:手永远不离开键盘主区。移动光标、选中文本、删除、复制、格式化等所有操作都可以使用键盘完成,而且绝大多数键都在手指自然放置的位置(如果不是也可以自己调hhh),可以完全脱离鼠标。
- 例:删除一个函数中的所有内容,使用别的编辑器需要先用鼠标选中函数体,再按删除键;而在vim例,光标在函数体内任意位置,
di{三个键就完成了。在函数内容很少时其实效率差别不大,但是一旦函数内容变多,几十行几百行,使用鼠标选中时还要拖动,还要找起始和结束位置,这时效率的差别就体现出来了。
- 操作的可组合型:
- Vim的编辑命令不是零散的快捷键,而是一套小语言。操作符、动作、计数词可以自由组合,最开始学习时会觉得很痛苦,但是随着学的越多,能力增长不是线性的,而是呈指数级的爆炸式增长。
- 无处不在:
- Vim几乎存在于所有Unix-like系统上,当远程一台服务器时,它不一定有vscode或其它现代化编辑器,但是一定有vim,这样就不会在没有vscode的时候束手无策
三、Vim怎么用
3.1 打开与退出
3.1.1 打开文件
# 打开文件(如果不存在则新建)
vim filename
# 打开多个文件
vim file1 file2
# 以只读模式打开
vim -R filename
# 打开文件并跳转到第10行
vim +10 filename
# 打开文件并跳转到第一个匹配pattern的位置
vim +/pattern file
3.1.2 退出vim
在Normal模式下:
- 退出(未修改文件时):
:q - 强制退出,不保存修改:
:w! - 保存并退出:
:wq,:x,ZZ,ZQ都可以 - 强制保存并退出:
:wq!
3.1.3 保存文件
在Normal模式下:
- 保存:
:w - 另存为:
:w filename - 保存所有打开的文件:
:wa
3.2 移动光标
在Normal模式下,Vim提供了极其丰富的移动方式。最基础的是:
h 向左移动一个字符
j 向下移动一行
k 向上移动一行
l 向右移动一格字符
Here is why vim uses hjkl keys as arrow keys
3.2.1 按词移动
w 移动到下一个词的开头
b 移动到上一个词的开头(如果光标在词中间则移动到当前词开头)
e 移动到当前词的末尾(如果已经在当前词的末尾则移动到下一个词末尾)
W 以空格为分隔移动到下一个“大词”的开头(跳过标点)
B 以空格为分隔移动到上一个“大词”的开头(跳过标点)
w和W的区别:w把标点符号也当作词的分隔,W只把空格当作分隔。比如在hello-word中,按w会停在-上,按W会直接跳到下一个空格后的词。
3.2.2 行内移动
0 移动到行首
^ 移动到本行第一个非空白字符
$ 移动到行尾
g_ 移动到本行最后一个非空白字符
3.2.3 按屏幕移动
H 移动到屏幕顶部(High)
M 移动到屏幕中间(Middle)
L 移动到屏幕底部(Low)
Ctrl+u 向上翻半页(Up)
Ctrl+d 向下翻半页(Down)
Ctrl+b 向上翻一页(Back)
Ctrl+f 向下翻一页(Forward)
zz 将当前行置于屏幕中央(Center?)
zt 将当前行置于屏幕顶部(top)
zb 将当前行置于屏幕底部(bottom)
3.2.4 按段落和代码块移动
{ 移动到上一个空行(段落开头)
} 移动到下一个空行(段落开头)
[[ 移动到上一个函数/代码块开头(在代码文件中)
]] 移动到下一个函数/代码块开头
% 在匹配的括号、引号之间跳转
3.2.5 文件内跳转
gg 移动到文件第一行
G 移动到文件最后一行
10G 移动到第10行
:10 移动到第10行
3.2.6 精确搜索跳转
f{char} 在当前行正向查找字符{char}并跳转(Find)
F{char} 在当前行反向查找字符{char}并跳转
t{char} 在当前行正向查找字符{char}并跳转到其前一个字符(Till)
T{char} 在当前行反向查找字符{char}并跳转到其后一个字符
; 重复上一次f/t/F/T查找
, 反向重复上一次f/t/F/T查找
f和t的区别:f(光标停在(上,t(光标停在(前一个字符上。
3.3 进入Insert模式
从Normal模式进入Insert模式有多种昂是,每种适用于不同场景:
i 在光标前插入(insert)
I 在本行第一个非空白字符前插入
a 在光标后插入(append)
A 在本行末尾插入
o 在下方另起一行插入(open)
O 在上方另起一行插入
s 删除光标所在字符并进入插入模式(substitute)
S 删除当前行并进入插入模式
cc 删除当前行并进入插入模式
C 删除当前光标到行尾并进入插入模式
一个常见的场景:光标在行中间的某个位置,你想在行尾添加内容。与其用l一步步移动到行尾再按i插入,不如直接按A一步到位,提升效率。
3.4 编辑操作
Vim的编辑操作可以理解为一种“语法”:操作符+动作/范围。理解这个组合逻辑后,Vim的编辑能力会豁然开朗。
3.4.1 核心操作符
d 删除(delete) - 实际上时剪切,删除的内容会存到寄存器
c 修改(change) - 删除后自动进入Insert模式
y 复制(yank)
p 粘贴到光标后(paste)
P 粘贴到光标前
x 删除光标所在字符(等价于d1和delete键)
X 删除光标前一个字符(等价于dh)
r 替换光标所在字符(replace),单个字符替换,不进入Insert模式
R 进入替换模式,连续替换多个字符
u 撤销(undo)
Ctrl+r 重做(redo)
. 重复上一次修改操作(Vim最强大的命令之一)
3.4.2 操作符+动作组合
这是Vim的精华所在,将一个操作符和一个移动命令组合,就能精确地操作任意范围的文本:
dw 删除一个词(delete word)
d2w 删除两个词
d$ 删除到行尾(同D)
d0 删除到行首
d^ 删除到本行第一个非空白字符
de 删除到当前词末尾
dgg 删除到文件开头
dG 删除到文件末尾
dd 删除整行
2dd 删除两行
ciw 删除当前光标所在词并进入插入模式(change inner word)
ci" 删除双引号内的内容并进入插入模式(change inner ")
ci( 删除括号内的内容并进入插入模式(change inner ())
ci{ 删除花括号内的内容并进入插入模式
da" 删除双引号及其内部内容(delete a ")
diw 删除当前词(不进入插入模式, delete inner word)
yiw 复制当前词
yy 复制整行
3yy 复制三行
y$ 复制到行尾
yG 复制到文件末尾
5p 粘贴5次
3.4.3 text-object
上面出现的iw(inner word)、i(inner quotes)、a(a quotes)是Vim的文本对象概念,是Vim最搞笑的特性之一。
i(inner)表示内部,不包含边界字符;a(a/an)表示一个完整的,包含边界字符和前后空格。
常用文本对象:
iw 一个词(inner word)
aw 一个词加后面的空格(a word)
iW 一个大词(以空格分隔)
aW 一个大词加后面的空格
i" 双引号内部
a" 双引号及其内部
i' 单引号内部
a' 单引号及其内部
i( 圆括号内部 — 等同于 i)
ib 圆括号内部(inner block)
i[ 方括号内部
i{ 花括号内部 — 等同于 iB
a( 圆括号及其本身
a[ 方括号及其本身
a{ 花括号及其本身
it HTML/XML 标签内部(inner tag)
at HTML/XML 标签及其内部(a tag)
ip 一个段落(inner paragraph)
ap 一个段落加后面的空行
is 一个句子(inner sentence)
as 一个句子加后面的空格
实用场景举例:光标在 "hello world" 中任意位置,按 ci" 会删除引号内的所有内容,光标定位在引号之间,等待你输入新内容。按 da" 则连引号带内容一起删除。
3.5 搜索与替换
3.5.1 文件内搜索
/pattern 正向搜索pattern
?pattern 反向搜索pattern
n 跳转到下一个匹配
N 跳转到上一个匹配
* 搜索光标所在的词(正向)
# 搜索光标所在的词(反向)
搜索时可以使用正则表达式。搜索后匹配项会高亮,用:noh关闭高亮,或用:set hlsearch/:set nohlsearch控制
3.5.2 替换
:s/old/new 替换当前行第一个old
:s/old/new/g 替换当前行所有old
:%s/old/new/g 替换全文所有old
:%s/old/new/gc 替换全文所有old,但每次确认
:10,20s/old/new/g 替换第10行到第20行的所有old
:%s/old/new/gi 替换全文所有old,忽略大小写
替换中的分隔符不一定是/,可以用任何字符,这在处理路径时非常方便:
:%s#/usr/local/bin#/opt/bin#g
3.6 多文件、多窗口与标签页
3.6.1 缓冲区(Buffer)
Vim中打开的每个文件对应一个缓冲区:
:ls 列出所有缓冲区
:bnext 切换到下一个缓冲区
:bprevious切换到上一个缓冲区
:b number 切换到编号为number的缓冲区
:bd 删除当前缓冲区(关闭文件)
:bd! 强制删除缓冲区,不保存
3.6.2 窗口(Window)
:split filename 水平分割窗口打开文件(:sp)
:vsplit filename 垂直分割窗口打开文件(:vp)
Ctrl+w h 切换到左边窗口
Ctrl+w j 切换到下面窗口
Ctrl+w k 切换到上面窗口
Ctrl+w l 切换到右边窗口
Ctrl+w w 在所有窗口间循环切换
Ctrl+w q 关闭当前窗口
Ctrl+w = 让所有窗口等宽等高
Ctrl+w _ 最大化当前窗口高度
Ctrl+w | 最大化当前窗口宽度
:only 关闭其他所有窗口(:on)
3.6.3 标签页(Tab)
:tabnew filename 在新标签页打开文件
:tabclose 关闭当前标签页
:tabnext 下一个标签页(:tabn)
:tabprevious 上一个标签页(:tabp)
gt 切换到下一个标签页
gT 切换到上一个标签页
3.7 寄存器与宏
3.7.1 寄存器
Vim有多达26个命名寄存器(a-z),加上系统剪贴板(+或*)、无名寄存器(")、数字寄存器(0-9)等。当yank或delete时,内容默认存入无名寄存器"。
"ayy 复制当前行到寄存器a
"ap 粘贴寄存器a的内容
"+y 复制到系统剪贴板
"+p 从系统剪贴板粘贴
:reg 查看所有寄存器内容
3.7.2 宏(Macro)
宏时Vim最强大的功能之一,可以录制一系列操作并重复执行:
qa 开始录制宏到寄存器a(可以用任何字母)
... 执行一系列曹祖
q 停止录制
@a 执行寄存器a中的宏
10@a 执行宏10次
@@ 重复上一次执行的宏
典型场景:有100行数据,每行需要做同样的格式化操作。在第一行录制宏qa,执行操作,q停止,然后99@a对剩余99行执行同样的操作
宏可以用搜索定位(/pattern),这样即使每行内容不同,也能精确找到操作位置
3.8 常用配置(~/.vimrc)
Vim的行为可以通过配置文件大幅定制。以下是一些常用的基础配置及其含义:
" 基础设置
set nocompatible " 关闭 vi 兼容模式
set number " 显示行号
set relativenumber " 显示相对行号(配合 j/k 跳转极其好用)
set cursorline " 高亮当前行
set showcmd " 在右下角显示未完成的命令
set showmode " 在左下角显示当前模式
set wildmenu " 命令行补全增强
" 缩进
set autoindent " 自动缩进
set smartindent " 智能缩进
set tabstop=4 " Tab 显示宽度
set shiftwidth=4 " 缩进宽度
set expandtab " 将 Tab 转换为空格
set softtabstop=4 " 按 Backspace 时一次删除 4 个空格
" 搜索
set hlsearch " 搜索高亮
set incsearch " 增量搜索(边输入边搜索)
set ignorecase " 搜索忽略大小写
set smartcase " 搜索中有大写字母时区分大小写
" 编码
set encoding=utf-8
set fileencodings=utf-8,gbk,gb2312,cp936
" 其他
set mouse=a " 启用鼠标支持
set clipboard=unnamed " 使用系统剪贴板
set history=1000 " 保留更多历史记录
set undofile " 持久化撤销(关闭文件后仍可撤销)
set swapfile " 启用交换文件防止崩溃丢失数据
set backup " 自动备份