vim小结
vim小结
详见Vim实用技巧(第2版) by [英] Drew Neil

0. vim哲学
- 操作符命令 + 动作命令 = 操作
.
范式:一键移动,一键执行
1. 操作符命令 (可以搭配动作motion)
-
c
: 修改 -
d
:删除 -
y
:复制到寄存器 -
g~
:反转大小写 -
gu/gU
:转换为小写/大写 -
> <
: 增加/减少缩进 -
=
:自动缩进 -
!
:使用外部程序过滤{motion}所跨越的行 -
i/I
: 字符/行 前插入 -
a/A
: 字符/行 后插入
-
I/A
:在可视模式中,插入位置高亮行的首位 -
s
:删除当前字符,切换到I_mode -
cw
: 删除光标位置到单词结尾间的字符,切换到I_mode -
f+
: 跳到当前行光标后下一个+处。用;可以重复此操作;可以用,返回到上一个+处(反向查找) -
t+
: 跳到当前行光标后下一个+前一个字符处。用;可以重复此操作;可以用,返回到上一个+后一个字符处(反向查找) -
.
: 相当于一个宏,录下了最近一次修改操作(从切换到I_mode到退出I_mode的所有编辑动作)。N_mode下可以重复执行 -
u
: 撤销上一次修改 -
*
:光标移到单词a处,执行*,会查找所有此单词a,按n下一个,N上一个 -
方向键:在I_mode中按方向键,会重置修改状态,会影响
.
命令,同样也会影响u
命令 -
b/B
: 光标移到上一个单词开头/光标移至以空格分隔的上一个单词块开头 -
w/W
: 光标移到下一个单词开头/光标移至以空格分隔的下一个单词块开头 -
ge/E
: 光标移至上一个单词结尾/光标移至以空格分隔的上一个单词块结尾 -
e/E
: 光标移至下一个单词结尾/光标移至以空格分隔的下一个单词块结尾 -
dw
: 删除光标到下一个单词开头间的字符。d3w删除三个单词 -
db
: 删除光标到单词开头间的字符,但留下光标开始处的字符。 -
daw
: 删除光标所在处的整个单词。delete a word -
0
: 移至行首 -
^
: 移至第一个非空白字元 -
$
: 移至行尾 -
A
: 跳到本行末尾,切换到I_mode -
ctrl+f/b
: 向下/上翻页 -
Ctrl+a/Ctrl+x
: 分别对数字执行加和减操作。eg. 180+Ctrl+x会在光标上或光标后第一个数字减去180 -
zz
: 将当前行显示在屏幕正中 -
ga
: 显示光标所在字符的编码,分别以10/8/16进制显示
2. 动作命令(可以搭配操作符)
-
kjhl
上下左右 -
gk/
屏幕行上。在所有实际行动作前加g,变成屏幕行动作 -
w/e
下一个单词开头/本词或下一个单词结尾 -
b/ge
上一个单词开头/本词或上一个单词结尾 -
W/E
下一个字串开头/本字串或下一个字串结尾 -
B/gE
上一个字串开头/本字串或上一个字串结尾 -
f{char}
正向移动到下一个 {char} 所在之处 -
F{char}
反向移动到上一个 {char} 所在之处 -
t{char}
正向移动到下一个 {char} 所在之处的前一个字符上 -
T{char}
反向移动到上一个 {char} 所在之处的后一个字符上 -
;
重复上次的字符查找命令 -
,
反转方向查找上次的字符查找命令 -
/pattern
查找pattern,并跳到那里。查找命令是一个开动作(不包含选中的词)
文本对象就是基于结构定义的文本区域 (如:(), {}, [])下面动作可以搭配v, d, c等操作使用:
-
i}
光标在{}内部时,此动作会选中{}内部文本 -
a}
此动作会选中{}内部文本包含括号。同理:)]>' "
一样适用 (i:inside, a:around) -
it
选中XML标签tags 内部 -
at
选中XML标签tags -
iw/aw
当前单词/当前单词及一个空格 -
iW/aW
当前字串/当前字串及一个空格 -
is/as
当前句子/当前句子及一个空格 -
ip/ap
当前段落/当前段落及一个空行
标记:
-
mm/`m 设置位置标记m/跳转到标记m
-
Vim的自动位置标记
-
``` ` 当前文件中上次跳转动作之前的位置
-
``. ` 上次修改的地方
-
``^` 上次插入的地方
-
``[` 上次修改或复制的起始位置
-
``] ` 上次修改或复制的结束位置
-
``< ` 上次高亮选区的起始位置
-
``>` 上次高亮选区的结束位置
-
跳转:大范围的移动
nG/ngg
跳转到指定的行号/pattern<CR>或?pattern<CR>/n/N
跳转到下一个/上一个模式出现之处%
跳转到匹配的括号所在之处(/)
跳转到上一句/下一句的开头{/}
跳转到上一段/下一段的开头H/M/L
跳到屏幕最上方/正中间/最下方gf
跳转到光标下的文件名<C-]>
跳转到光标下关键字的定义之处’{mark}/
` 跳转到一个位置标记
3. 插入模式 I_mode
ctrl+h
;删除前一个字符(backspace)ctrl+w
: 删除前一个单词ctrl+u
: 删除至行首Esc/Ctrl+[
: 切换到N_modectrl+o
: 切换到插入-普通模式。即在插入模式执行此命令,回到普通模式执行一个命令,自动返回插入模式<ctrl+r>{register}
:在I_mode中将register中的内容复制到光标处<Cr>=
:会在I_mode下访问表达式寄存器,输入一个表达式按下<CR>
,返回的值就会以文本形式写到光标处<C+v>{123}
: 以十进制字符编码插入字符<C+v>u{123}
: 以十六进制字符编码插入字符r/R
:进入替换模式,单字符/多字符替换。输入完可以按<Esc>
返回普通模式,也可以用<Insert>
在插入和替换模式间切换
4. 可视模式V_mode
v/V
:切换到字符/行可视模式<C+v>
: 块选中,相当于notepad中的alt+鼠标gv
: 重选上次的高亮选区o
切换高亮选区的活动端。高亮选区有2个端点,此命令可以切换活动端点viw
高亮选择当前光标所在的词
5. 命令行模式C_mode
:
切换到此模式/
调出查找提示符或用<C-r>=
访问表达式寄存器:[range]delete [x]
删除指定范围内的行到寄存器x中:[range]yank [x]
复制指定范围的行到寄存器x中:[line]put [x]
在指定行后粘贴寄存器x中的内容:[range]copy {address}
把指定范围内的行拷贝到 {address} 指定的行之下:[range]move {address}
把指定范围内的行移动到 {address} 指定的行之下:[range]join
连接指定范围内的行:[range]normal {commands}
对指定范围内的每一行执行普通模式命令:[range]substitute/{pattern}/{string}/[flags]
把指定范围内出现{pattern}的地方替换为:[range]global/{pattern}/[cmd]
对指定范围内匹配{pattern}的所有行执行命令:1/:$
跳到文档开头/结尾:p
显示当前行的内容:3d
跳到第3行并删除此行:2,5p
行号指定范围:显示第2行到第5行之间的每一行的内容(含第2行及第5行)。运行完后,光标将停留在第5行。
其中:2,5是地址(行号), 类似的:
. 代表当前行的地址
.+1 代表当前行下一行的地址
$ 代表最后一行的地址
% 代表文件中的所有行:/<html>/,/<\/html>/p
模式指定范围:显示<html>
到</html>
之间的每一行的内容。:<Up/Down>
回溯命令行命令历史:help<Up>
回溯以help开头的命令q:/:q
进入/退出命令行窗口:!ls
调用SHELL程序%
在Vim的命令行中代表当前文件名:shell/exit
从vim进入shell/返回vim // 相当于把vim切换到后台。用ctrl+z/fg效果相同:read !{cmd}
把命令的标准输出重定向到缓冲区:write !{cmd}
在shell中执行当前缓冲区中的每行内容:[range]!{cmd} range
指定的行会传给 {cmd} 作为标准输入
6. 文件
-
缓冲区
-
:ls
查看当前打开的缓冲区列表1 %a "a.c" 第 5 行 2 # "test.py" 第 5 行 3 "tmp" 第 6 行 其中:%a 当前编辑文件、# 轮换文件
-
:bn/:bp/b2
跳转到下个/上个/第二个文件 -
:2bd
删除2号缓冲区 -
ctrl+^
在%a和#间快速切换
-
-
参数列表
:args
列出参数列表:args filename
指定文件名打开
-
隐藏缓冲区
:w[rite]
把缓冲区内容写入磁盘:e[dit]!
把磁盘文件内容读入缓冲区(即回滚所做修改):qa[ll]!
关闭所有窗口, 摒弃修改而无需警告:wa[ll]!
把所有改变的缓冲区写入磁盘
-
分割窗口
vim -o/O file1 file2 file3
三个文件水平/竖直分割<C-w>s
水平切分当前窗口, 新窗口仍显示当前缓冲区<C-w>v
垂直切分当前窗口, 新窗口仍显示当前缓冲区:sp[lit] {file}
水平切分当前窗口, 并在新窗口中载入:vsp[lit] {file}
垂直切分当前窗口, 并在新窗口中载入<C-w>w
在窗口间循环切换<C-w>h/j/k/l
切换到左/下/上/右的窗口:clo[se]/<C-w>c
关闭活动窗口:on[ly] /<C-w>o
只保留活动窗口, 关闭其他所有窗口= 使所有窗口等宽、 等高 <C-w>_
最大化活动窗口的高度<C-w>|
最大化活动窗口的宽度[N]<C-w>_
把活动窗口的高度设为[N]行[N]<C-w>|
把活动窗口的宽度设为[N]列
-
标签页
vim -p file1 file2 file3
三个标签页:tabe
新建未命名的标签页:tabe file
在新标签页中打开或新建文件file:tabnew
和tabe命令功能一样:tab split
在新标签页中打开当前窗口(缓冲区)的文件:tabs
列出已打开的标签列表,">"表示当前标签页:tabn/gt
移动到一个标签页(next):tabp/gT
移动到上一个标签页(previous):tabfirst/:tabr
移到第一个标签页:tablast
移到最后一个标签页:tabm 0
当前标签页移到第一个标签页:tabm
当前标签移到最后:tabc
关闭当前标签页:tabo
关闭当前标签以外的标签页
-
打开保存文件
:edit filename
不用退出vim打开文件:edit %<TAB>
% 符号代表活动缓冲区的完整文件路径, 按键会将其展开 :edit %:h<Tab>
% 符号代表活动缓冲区的完整文件路径(去掉文件名), 按键会将其展开 :w
保存文件:saveas
另存为:find filename
在当前目录查找文件。如果文件不在当前目录,需配置PATH::set path+=app/**
后会查找app目录及子目录
7. 寄存器reg:在vim中,剪切、复制的内容会存放在寄存器中
- vim中有如下寄存器:
""
无名reg。不指定寄存器的情况下,默认使用它"0
复制专用reg"a – "z
有名reg"_
黑洞reg 有去无回的地方"+
X11剪贴板, 用剪切、 复制与粘贴命令操作。"*
X11主剪贴板, 用鼠标中键操作"=
表达式reg。在插入模式下运行=i ,就可以把"=中的值插入到文档中 - 可读reg:
"%
当前文件名"#
轮换文件名".
上次插入的文本":
上次执行的Ex命令"/
上次查找的模式
"+p/<C-r>+
粘贴从外部程序中用剪切或复制命令获取的文本/I_mode下粘贴
"+y
复制到剪切板,给外部程序使用:reg "0
查看无名、复制专用regxp
可被用于“调换光标之后的两个字符p/P
命令旨在将寄存器中的文本粘贴到光标之后/前gp/gP
命令旨在将寄存器中的文本行粘贴到当前行之后/前
8. 宏:可以将一系列操作录制到寄存器中,以便后续复用
qa/q
开始录制宏到"a/停止录制qA/qB
给a/b宏追加命令qaq
清空寄存器a@a/@@
调用"a中的宏/重复调用上次宏n@a
串行。重复调用宏n次,如果执行过程中宏里面的动作或命令失败,宏会终止。其余次数别丢弃- 高亮选中多行,再在命令行
normal @a
并行。即使过程中失败,仍然会执行完 :put a
将宏a写在缓冲区"ay$
将修改后的宏写到宏a
9. 模式 (pattern)
-
\c or \C
本次查找忽略大小写 or 区分大小写 -
\v or \V
正则表达式(模式查找) or 原义查找 -
查找:
/target
正向查找target?xxx
反向查找n/N
下一个/上一个匹配gn/gN
进入面向字符的可视模式,并选中下一处/上一处匹配
-
替换
-
:[range]s[ubstitute]/{pattern}/{string}/[flags]
用string替换patternflags: g 在全局范围内执行,即可以修改一行内的所有匹配,而不仅仅是第一处匹配 c 可以确认或拒绝每一处修改 y 替换此处匹配 n 忽略此处匹配 q 退出替换过程 l “last” 替换此处匹配后退出 a “all” 替换此处与之后所有的匹配 <C-e> 向上滚动屏幕 <C- y > 向下滚动屏幕 n 让 Vim 不执行替换操作,而只是报告本次命令匹配的个数 e 屏蔽错误提示 & 指示Vim重用上一次substitute命令所用过的标志位
-
g&
可在整个文件的范围内重复上条命令。 -
:'<,'>&&
对高亮取重复上条命令。第一个&重复上一次的:substitute命令,但它会忽略标志位; 第二个&重用上一次:s命令的标志位
-
-
global命令
:[range]global[!]/{pattern}/[cmd]
:在缺省情况下,:global
命令的作用范围是整个文件(%)。而大多数Ex命令(包括:delete
、:substitute
以及:normal
) 有所不同, 这些命令的缺省范围仅为当前行(.) 。cmd缺省是print:global! or :vglobal
反转。即对不匹配的执行cmd:g/TODO/yank A
将所有匹配模式/TODO/的文本行依次附加到寄存器a:'<,'>sort
对高亮选中排序
10. 自动补全
<C-n>
普通关键字<C-x><C-n>
当前缓冲区关键字<C-x><C-i>
包含文件关键字<C-x><C-]>
标签文件关键字<C-x><C-k>
字典查找<C-x><C-l>
整行补全<C-x><C-f>
文件名补全<C-x><C-o>
全能(Omni) 补全<C-n>
使用来自补全列表的下一个匹配项(next 匹配项)<C-p>
使用来自补全列表的上一个匹配项(previous 匹配项)<Down>
选择来自补全列表的下一个匹配项<Up>
选择来自补全列表的上一个匹配项<C-y>
确认使用当前选中的匹配项(yes)<C-e>
还原最早输入的文本(从自动补全中exit)<C-h>(与 <BS>)
从当前匹配项中删除一个字符<C-l>
从当前匹配项中增加一个字符{char}
中止自动补全并插入字符
11. 插件
更多插件访问:https://vimawesome.com/
-
matchit.vim
-
Surround.vim
-
ctags: 代码中关键字的标签
sudo apt-get install exuberant-ctags cd 目标目录,执行ctags *.c 进入vim, 执行:set tags=./tags :!ctags -R 手动更新标签。也可以映射:nnoremap <f5> :!ctags -R<CR>
12. vim键盘按键映射标识符

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通