Vim
[count]<C-a>
从当前光标处正向查找一个数字进行自增[count]<C-x>
从当前光标处正向查找一个数字进行自减.
重复命令, 会重复进入插入模式那一刻起(包括进入插入模式的按键本身),直到返回普通模式为止的输入或上一个普通模式下的操作(daw这样的命令会被视作一个操作),
可以被看作一个微型的宏命令.
j.
在下一行里重复之前的操作n.
在下一个匹配里重复之前的操作在为
.
范式预备插入模式命令时, 使用方向键(<Up>
<Down>
<Left>
<Right>
)会产生撤销块,导致连续的命令被中断(可以想象成是用
<Esc>
退出了插入模式, 然后用 hjkl
做了移动).
范式优于使用count的命令, 例如 dw.
要优于 d2w
, 原因在于估计count的值很不直观, 多按几次 .
反而好控制.i
进入插入模式gi
在上一次退出插入模式的位置进入插入模式<C-u>
删除至行首(此快捷键在Bash也可使用)<C-w>
删除上一个单次(此快捷键在Bash也可使用)<C-r>{register}
插入寄存器内容(插入模式下)<C-r>={expression}<CR>
插入表达式寄存器, 将输出表达式的计算结果<C-r><C-p>{register}
插入寄存器内容(paste模式)Vim使用基于树而不是队列的历史记录, 撤销前的内容会作为一个分支保留.
按分支操作是把树当作一般的文本编辑器里的队列, 因此无法访问其他分支.
u
按分支撤销 undoU
按分支撤销对整行的操作<C-r>
按分支重做 redo按时间操作是按时间顺序访问树.
g-
按时间回退改动g+
按时间前进改动在输入前几个字之后按
按
<C-n>
将出现自动补全窗口(如果只有一个, 则直接补全),按
<C-n>
切换到下一个补全项, 按 <C-p>
切换到上一个补全项.<C-x><C-i>
补全整行<C-x><C-j>
补全标签<C-x><C-f>
补全文件名gd
跳转到下一个当前光标处的内容定义的位置gD
跳转到下一个当前光标处的内容定义的位置(从文件开头查找)使用
ctags -R
生成标签文件tags.每次保存ts文件时自动生成标签文件(autocmd自动命令):
autocmd BufWritePost *.ts silent! !ctags -R &
以下命令需要标签文件tags才能使用
<C-]>
跳转到定义 在VSCode里可直接使用<C-t>
跳转回原文件 在VSCode里可直接使用:tn
下一个标签 tag next:tp
上一个标签 tag previous:ts
打开标签列表菜单 tag select<C-o>
在插入模式下进入插入-普通模式, 在该模式下可以完成一个普通模式动作,然后自动回到插入模式, 该模式的优点在于可以省去一个进入插入模式的按键
<C-o>:w<CR>
快速保存<C-[>
切换到普通模式, 跟用<Esc>退回普通模式似乎没有区别插入模式
插入模式
插入模式
插入模式
<C-v>{code}
插入非常用字符(三位数的十进制字符编码)插入模式
<C-v>u{code}
插入Unicode字符(四位十六进制字符编码)插入模式
<C-v>{nondigit}
按照原义插入字符, 例如 <C-v><Tab>
插入制表符(无视expandtab设置)插入模式
<C-k>{char1}{char2}
插入二合字符, 例如 <C-k>12
插入 ½
, <C-k><<
插入 «
ga
显示当前光标字符的编码vi时代的缓冲区列表, vim时代用于批量执行命令.
由于vim不会将打开的文件自动填入参数列表, 因此避免将不必要的文件卷入命令执行.
由于vim不会将打开的文件自动填入参数列表, 因此避免将不必要的文件卷入命令执行.
:args {arglist}
填充参数列表, 例如 :args index.html app.js
即可打开两个文件,参数列表可使用glob模式批量添加, 甚至执行命令
:args `cat .chapters`
以文件内容作为参数:first
:next
:previous
:last
:arg {file1} {file2}
定义参数列表:arg **/*.ts
递归定义参数列表(将所有ts文件放进参数列表):argdo {ex-command}
对参数列表中的所有文件执行一条命令:argdo %s/\<animal\>/creature/ge | update
将参数列表内的文件执行替换, 并保存(update, 等价于 :write
):args
显示参数列表vim时代的参数列表的替代品, vim多文件编辑的本质是一次将多个文件内容读入多个缓冲区, 保存则为将缓冲区内容写入文件.
:b[uffer] n
切换到第n个文件:bfirst
列表中第一个文件:blast
列表中最后一个文件:bn[ext]
切换到下一个文件:bp[rev]
切换到上一个文件:b file
按文件名切换:ls
或 :buffers
或 :files
列出打开的文件, 这是vim引入的功能, vi只有 :args
<C-^>
在当前文件和轮换文件之间快速切换:bufdo
类似argdo, 在打开的缓冲区上执行Ex命令:bd[elete] N1 N2 N3
删除缓冲区(即退出编辑), 也可用 :n1,n2bd
批量删除, 按Tab可自动补全文件名:qa[ll]
关闭所有缓冲区:wa[ll]
写入所有缓冲区:wn[ext]
写入当前缓冲区并切换到下一个缓冲区内置文件浏览器, 支持sftp, scp等协议.
:Ex
或 :Explore
打开Netrw:e {directory}
指定目录打开Netrw:Vex
左右分割打开Netrw:Sex
上下分割打开Netrw:Lex
左右分割打开Netrw, 并将Netrw窗口置于最左侧Enter
打开文件-
上级目录D
删除文件或目录R
重命名文件或目录知名的侧边文件浏览器插件, 支持鼠标.
:NERDTree
打开NERDTree:NERDTreeToggle
开关NERDTreeEnter
或 o
打开文件vim -On file1 file2
左右分屏打开多文件 openvim -on file1 file2
上下分屏打开多文件vim + file
打开文件并跳转至最后一行<C-w>s
或 :sp[lit]
水平分屏当前文件 split:sp[lit] {file}
水平分屏当前文件 or 新文件<C-w>v
或 :vsp[lit]
垂直分屏当前文件 vertical:vsp[lit] {file}
垂直分屏当前文件 or 新文件<C-w>h
切到左窗口<C-w>l
切到右窗口(以此类推上 k
下 j
)<C-w>H
移动至左侧窗口<C-w>L
移动至右侧窗口(以此类推上 K
下 J
)<C-w>w
循环切换窗口, 也可以直接 <C-w><C-w>
<C-w>+
加大窗口<C-w>-
减小窗口<C-w>=
所有窗口等高等宽<C-w>_
最大化当前窗口高度<C-w>|
最大化当前窗口宽度[N]<C-w>_
设置当前窗口高度为N行[N]<C-w>|
设置当前窗口宽度为N列<C-w>c
关闭当前窗口 close<C-w>q
关闭当前窗口并退出 quit<C-w>o
或 :on[ly]
关闭当前窗口以外的所有窗口:lcd {path}
为当前窗口设置工作目录:pwd
查看工作目录:windo lcd {path}
为所有窗口设置工作目录:edit {filename}
相对当前工作目录打开文件:edit!
放弃修改重新载入当前文件, 通常用于录制宏时对操作过的文件进行撤销,
以便将宏应用于所有缓冲区文件时不会重复运行:e[dit] %<Tab>
用%<Tab>
补全当前缓冲区文件(即当前文件)的路径, 便于相对当前文件路径打开其他文件:e[dit] %:h<Tab>
上一补全命令的相对路径版本,:h
是一种文件名修饰符(用:h ::h
查看说明文件):e[dit] .
打开目录, 空格可以省略:find {filename}
不使用完整路径打开文件文件,
例如:find Main.js
输入文件名后也可以用<Tab>
补全文件路径
(建议补全路径, 否则在有同名文件的情况下只会打开第一个):set path+=app/**
添加find的查找路径:set path?
查看当前path路径gf
打开当前光标处的文件(受path和suffxiesadd影响):set suffixesadd+=.js
为gf
功能添加.js
扩展名:!mkdir -p %:h
在写入不存在目录的文件时, 创建那个目录:w !sudo tee % >/dev/null
以root权限写入
原理为将当前缓冲区(文件)内容作为输入重定向给具有root权限的tee, 再由tee写入到对应文件,
用/dev/null屏蔽掉多余的打印内容:clo[se]
关闭当前窗口(只剩一个窗口时不能关闭, 这是与:quit的主要区别):on[ly]
只保留当前窗口, 关闭其他窗口
vimdiff {filename1} {filename2}
]c
跳转到上一个冲突[c
跳转到下一个冲突do
将文件修改应用于当前窗口中的文件 diff obtaindp
将当前窗口中的文件修改推送给另一个文件 diff put:diffg[et] {file}
相当于do, 在同时比较3个文件以上时, 需要后接文件名:diffp[ut] {file}
相当于dp, 在同时比较3个文件以上时, 需要后接文件名在git处理合并冲突时使用vimdiff
左上角的窗口为本地修改(当前分支)
中上的窗口为共同祖先
右上角的窗口为远程修改(合并进来的分支)
下方的窗口为合并结果(需要通过编辑解决冲突的文件)
删除
git mergetool
左上角的窗口为本地修改(当前分支)
中上的窗口为共同祖先
右上角的窗口为远程修改(合并进来的分支)
下方的窗口为合并结果(需要通过编辑解决冲突的文件)
:diffg L
使用本修改 LOCAL:diffg B
使用共同祖先 BASE:diffg R
使用远程修改 REMOTE:wqa
保存并退出删除
.orig
文件(合并冲突的备份):w `date`
使用Shell命令的输出作为文件名保存:set foldmethod=indent
启用基于缩进的折叠功能:set foldmethod=syntax
启用基于语法的折叠功能(需要Vim能够识别该语法):set foldmethod=diff
处于diff时采用的折叠方式zo
打开折叠 openzc
关闭折叠 closeza
切换折叠状态zR
打开所有折叠zM
关闭所有折叠::tabnew
或 tabe[dit] {filename}
打开一个新的标签页<C-w>T
把当前窗口移到一个新标签页:tabc[lose]
关闭当前标签页及其所有窗口:tabo[nly]
只保留当前标签页,关闭其他所有标签页:tabn[ext] {N}
或 {N}gt
切换到标签页Ngt
或 :tabn[ext]
切换到下一标签页gT
或 :tabp[revious]
切换到上一标签页:tabmove [N]
将标签页移动至N, 0为第一个标签页, 若省略N, 则移到最后一个标签页:x
保存退出(相当于 :wq?
):qa!
强制退出所有文件 quit all:e file
打开另一个文件:e!
放弃对文件的所有修改, 恢复原样ZZ
保存当前文件并退出(:wq
的别名)Ctrl+G
显示当前编辑文件状态信息(文件名, 当前行, 总行数, 百分比等)<C-O>
(在查找等操作之后)返回上一次光标所处的位置, 可重复使用<C-I>
反向的 <C-O>
r
修改单个字符, 在可视模式下, 将以单个字符填充所有选中的字符 replaces
删除当前字符并进入插入模式S
删除当前行并进入插入模式(会保持缩进, 功能与cc一样)c{motion}
删除并进入插入模式cc
删除整行并进入插入模式(会保持缩进)cw
删除单词并进入插入模式C
删除至行尾(和 D
不同, 不会回退到上一个字符)D
剪切至行尾(会回退到上一个字符, 相当于 d$
)gj
根据屏幕行向下移动gk
根据屏幕行向上移动g^
移动到屏幕行的第一个非空字符g$
移动到屏幕行的行尾v <motion> :w filename
将选区内容保存为新文件:h index
查看Vim默认的按键绑定:map {key}
查看以对应按键key开头的映射:unmap {key}
取消对应的重映射:mapclear
清除所有重映射:map ^M I#<ESC>
设置递归快捷键映射, 例子意为Ctrl+M映射为I#<ESC>(在行首插入#然后退出插入模式):noremap ^M I#<ESC>
设置非递归映射:nnoremap ^M I#<ESC>
设置正常模式下的非递归映射:vnoremap ^M I#<ESC>
设置可视模式下的非递归映射:inoremap ^M I#<ESC>
设置插入模式下的非递归映射:ab email user@example.com
设置字符宏, 输入email(需要追加一个空白字符)会被自动替换为 user@example.com
:ce
居中 center:le
靠左 left:ri
靠右 right进入块视图模式, 选中多行文本, 用
I
在选中内容前批量插入字符 //
.进入块视图模式, 选中需要删除的内容, 用
d
命令删除.0
行首^
或_
非空白字符行首$
行尾g_
非空白字符行尾w
移动光标到下一个"狭义单词(以符号为分隔符)的开头" wordW
移动光标到下一个"广义单词(以空格为分隔符)的开头"b
移动光标到上一个"狭义单词(以符号为分隔符)的开头 backwardB
移动光标到上一个"广义单词(以空格为分隔符)的开头"e
移动光标到下一个"狭义单词(以符号为分隔符)的结尾"
(如果当前光标在一个单词的非结尾处, 那么下一个"单词的结尾"即是当前单词的结尾处, 而非"下一个单词"的结尾)E
移动光标到下一个"广义单词(以空格为分隔符)的结尾"ge
移动光标到上一个"单词的结尾"fa
移动光标到本行下一个字符为a的位置 findFa
移动光标到本行上一个字符为a的位置ta
移动光标到a前的一个字符, till, 这个命令通常用于dt.(删除至下一个句号前)这样的动作Ta
移动光标到a后的一个字符(
移动至句首(以". "作为一句, 注意句号后的空格))
移动至句尾(以". "作为一句, 注意句号后的空格){
移动到上一个段落(空白行)}
移动到下一个段落(空白行);
向后重复f
,t
操作,
向前重复f
,t
操作d/something
删除至something, 这提供了正则删除能力gg
或H
或1G
或[[
或``
文件首行G
或]]
文件末行H
光标移动至编辑区(window)首行 head line of windowM
光标移动至编辑区(window)中间 middle line of windowL
光标移动至编辑区(window)末尾 last line of windownG
移动光标到第n行nH
移动光标到第n行(ngg
同理)%
在配对的括号字符上来回移动, 有效字符为()[]{}
*
查找当前光标处的单词#
反向查找当前光标处的单词(这两个命令实际上是为了快捷使用而创建出来的宏命令)g*
查找当前光标处的单词, 但不使用单词界定符g#
反向查找当前光标处的单词, 但不适用单词界定符n%
到文件n%的位置
可视范围
zz
当前行置于屏幕中间zt
当前行置于屏幕顶端 topzb
当前行置于屏幕底端 bottom<C-f>
下一页 forward<C-b>
上一页 back<C-u>
上半页 up<C-d>
下半页 down<C-e>
向下一行<C-y>
向上一行dfa
删除至下一个字符 a
dnfa
删除至第n个字符 a
dH
删除至文本首dG
删除至文本尾daw
删除光标位置所处的单词至下一个单词的第一个字符(dw只删除当前光标位置到下一个单词的第一个字符)yw
复制单词yfa
复制至下一个字符aynfa
复制至第n个字符ay$
复制至行尾yH
复制至文本首yG
复制至文本尾J
合并下一行内容至本行(删除两行之间的换行符和其他空白符) 两行中间会有一个空格gJ
两行中间没有空格的 J
:1,10m20
将1到10行的内容移动到20行后 movei
inside,不包括文本对象边界,只针对内容a
around,包括文本对象边界s
句子 sentencew
狭义单词 wordW
广义单词p
段落t
HTML标签"
双引号'
单引号(
括号<
尖括号[
方括号{
花括号可以用
v{i|a}{文本对象}
方式直接框选相关内容P
复制至光标前 paste插件
<Leader><Leader>w
开启基于单词的EasyMotion, 最常用(同理, 还有 W
, b
, B
, e
, E
, ge
, gE
)<Leader><Leader>f
开启正向查找字符的EasyMotion(同理, 还有 F
, t
, T
)<Leader><Leader>{方向键}
朝对应的文本方向开启EasyMotion在搜索时
<Leader><Leader>n
开启用于跳转到搜索结果的EasyMotion(同理, 还有 N
)<Leader>
先导键, 默认为 \
let mapleader = "\<space>"
将先导键修改为空格(于 .vimrc
中设置)u
转小写字母 等于普通模式下的 gu{motion}
例如 guit
U
转大写字母 等于普通模式下的 gU{motion}
例如 gUit
注意可视模式下的命令用
.
重复执行时,选取和动作会被视为两条命令,将导致一些问题(例如选区长度被固定为一定数量的字符).
正确的方法是使用
g
开头的命令一次完成选取和动作, 这样 .
命令就可以正确执行.o
光标跳转至选区另一端, 该命令用于调整选区范围gv
重选中上次选区{number}|
跳转到指定列{number}gg
或 :{number}
跳转到指定行:+{number}
向下相对跳转到指定行:-{number}
向上相对跳转到指定行ma
标记此处为a'a
跳转至a标记:marks
查看所有标记:delm!
删除所有标记m{a-z}
缓冲区范围内的位置标记m{A-Z}
(多文件)全局范围内的位置标记'{a-zA-Z}
跳转到标记所在行`{a-zA-Z}
跳转到标记所在行和列``
跳转到上次跳转之前的位置, 常见用法是配合 %
跳转修改成对括号, %r{w}``r{w}
`<
上次高亮选区的起始位置`>
上次高亮选区的结束位置同理也存在
'
相应的跳转, 只不过 '
跳转到对应行不常用的跳转:
`.
上次修改(即跳转到改变列表的最后一位)`^
上次插入gi
跳转到上次插入位置并进入插入模式(相当于 `^i
)`[
上次修改或复制的起始位置`]
上次修改或复制的结束位置Vim 8.1开始提供的模式, 可在Vim内打开一个终端窗口.
:term[inal]
打开终端:term {command}
打开终端并执行命令r
(进入单字符替换模式)替换光标当前字符 replaceR
(进入替换模式)替换光标后的所有字符(用 <ESC>
停止)Vr{char}
替换整行字符为char~
改变当前字符的大小写n~
改变n个字符的大小写g~~
改变整行的大小写gUU
改变整行至大写guu
改变整行至小写3gUU
改变三行至大写gUw
改变单词至大写guw
改变单词至小写<C-v>
块可视化模式(可以无视行的长度选中文本块, 但在Terminus里无法使用, 疑似因为 <C-v>
被屏蔽)在块可视化模式内用
I
或 A
, 可以实现在选中的文本块的行前或后添加文本(将批量作用到选中文本块的每一行)va"
在""
文本块内部, 可用此命令选中该文本块的所有内容,"
可替换为其他文本块字符,
例如(
,'
,{
,[
vi"
同上, 但不选中"
本身
<C-n>
或 <C-p>
代码提示(编辑模式下)qa
开始录制宏并保存到寄存器aaA
开始录制宏并追加到寄存器aq
停止宏录制@a
应用位于寄存器a的宏@@
应用上一个宏n@a
应用a宏n次:'<,'>normal @a
进入V模式后批量运行宏a, 在这种运行方式里宏a在一行中运行失败不会中断其他行的运行:argdo normal @a
批量运行宏a至参数列表中的文件, 有必要对录制文件执行 :edit!
撤销修改, 避免重复运行:argdo execute ":normal @a" | update
批量运行宏a至参数列表中的文件并保存:new
打开新的缓冲区"ap
输出宏a的内容_"ay$
将新缓冲区的内容复制回宏a:reg
查看所有寄存器:reg {register}
查看寄存器:put a
输出寄存器a的内容到下一行"add
或 :d a
将行内容写回寄存器a, 用 "ay$
写回寄存器时可以免去行尾的换行符""
无名寄存器 即 d
, s
, x
, y
, c
命令默认使用的寄存器"_
黑洞寄存器, "_d{motion}
, 删除的内容不会进入任何寄存器"0
复制专用寄存器, 当使用 y
命令时, 相关内容不仅会进入无名寄存器, 也会进入此寄存器,此寄存器被用于解决
d
等命令覆盖无名寄存器以至复制内容消失的问题;但实际上也可以用
v
选中需要被替换的文本, 直接用 p
命令覆盖, 就不需要使用此寄存器"{a-z}
寄存器, "ad{motion}
可将内容输入进寄存器a, "ap
粘贴寄存器a信息"{A-Z}
追加寄存器, 将寄存器名从小写改为大写字母时, 新内容不会覆盖原寄存器, 而是追加到原内容之后"+
系统剪贴板"*
X11窗口系统的主剪贴板(primary), 与鼠标中间有关, Windows和macOS无此概念,该功能可在编译Vim时被禁用(xterm_clipboard)
"=
表达式寄存器, 可用来计算只读寄存器
"%
当前文件名"#
轮换文件名".
上次插入的文本":
上次执行的Ex命令"/
上次查找的模式Vim的copy使用y(yank)而不是c是历史原因, 在添加复制命令时, c键已经被用于change命令, 而y键还未被使用
- 命令行模式按下
<c-d>
, 显示所有补全项 - 命令行模式按下
<Tab>
, 自动补全 - 命令行模式
<C-r><C-w>
复制光标单词(word)插入至命令行,
在使用s命令进行文本替换时比较有用, 在开启insearch的情况下, 也可以用来直接补全匹配词 - 命令行模式
<C-r><C-a>
复制光标字串(WORD)插入至命令行
单词(word)的定义: 符合英文语法的单词(单词可以被符号隔开, 比如
字串(WORD)的定义: 任何以空格字符分隔开的非空白字符
we're
算两个单词)字串(WORD)的定义: 任何以空格字符分隔开的非空白字符
>>
缩进行:[range]> {count}
缩进行的ex命令形式<<
反缩进行:[range]< {count}
反缩进行的ex命令形式>G
缩进至文件末尾<G
反缩进至文件末尾:1
首行:$
尾行:0
虚拟行(位于首行上方):.
当前行:'m
包含位置标记m的行:'<
高亮选区起始:'>
高亮选取结束:%
整个文件, 相当于 :1,$
:.,.+3
选取当前行(.
)和后三行:/<html>/,/<\/html>/
正则选区:/<html>/+1,/<\/html>/-1
正则选区(偏移n行, +1
可省略为 +
):copy
复制选区, 详见 :h :copy
:move
移动选区, 详见 :h :move
:normal
执行普通模式命令, 详见 :h :normal
, 例如 :'<,'>normal .
意为对高亮选区里的每一行使用 .
命令:@:
或直接在普通模式下 @:
或 @@
重复上一条Ex命令:shell
打开一个新的shell, exit后即可回到Vim窗口(如果不想打开新的shell, 也可以用
<C-z>
暂停Vim, 回到原来的shell里, 做完其他事后再用fg回到Vim):term
以分屏的形式打开一个shell, 常用:sil[ent]
屏蔽输出n1,n2d
删除n1到n2(等同于sed的 d
命令)同理存在
:#,#s
在范围内查找g标志位指一整行范围(来源于行编辑器ed), 而不是全局(
%
才是全局):%s/find/replace/i
大小写不敏感的替换 ignoreCases:%s/find/replace/gc
需要人工确认的全局替换 check- magic
此为默认模式, 只有极少数符号不需要转义 - no magic
所有符号都需要用反斜线\
转义 - very magic
数字, 字母, 下划线以外的字符都是特殊字符, 通过在正则表达式首加入\v
启用此模式
:%s/\(\w\)/\1/g
捕获并替换, 括号在very magic模式以外的情况下必须转义\c
此元字符在正则中强制忽略大小写敏感\C
此元字符在正则中强制大小写敏感\v
此元字符在正则中开启very magic模式(符合Python, Perl, Ruby语法的正则模式),
该模式下
_
, 数字, 字母以外的字符都被当作特殊字符, 避免大量使用转义, 有效节省字符数和增强可读性/\<word\>
搜索整个单词 /\bword\b
搜索整个单词(Vim for VSCode)\<
单词开始\>
单词结尾<\w+>
very magic模式下的单词边界零宽度元字符(单词定界符),用
<
和 >
包裹字符部分(在一般模式下需要对 <
和 >
转义)%(a|b)
very magic模式下的非储存匹配, 在圆括号前加上 %
,匹配内容不会被存入寄存器
\1
, 类似于正则的 (?:pattern)
\V
此元字符在正则中强制只有 \
带有特殊含义(实际上在正向查找时有 /
作为结束符,反向查找时有
?
作为结束符, 所以是三个, 在查找URL时非常容易碰到此情况), 在只想按照原义匹配时很有用\x
此元字符代表 [0-9a-fA-F]
, 即十六进制数\zs
零宽度元字符 匹配边界开始 功能类似于正则的断言 (assert) (?=pattern) (?!pattern) (?<=pattern)
\zs
零宽度元字符 匹配边界结束 功能类似于正则的断言 (assert) (?=pattern) (?!pattern) (?<=pattern)
例子: 假设有一段文本
Goodbye World, Hello World
,需要匹配World, 但只匹配前面是Hello的World, 使用
/Hello \zsWorld<CR>
即可完成匹配(高亮项目为World)在查找时使用寄存器的方法:
在查找时使用寄存器并转义的方法:
(光标不在最后一个字符时将选中匹配项的剩余字符, 光标在最后一个字符时将选中至下一个匹配项的第一个字符)
衍生:
/\V<C-r>a<CR>
其中 <C-r>a
即输出寄存器a的值在查找时使用寄存器并转义的方法:
/\V<C-r>=escape(@a, getcmdtype().'\')
其中escape是内置转义函数,getcmdtype
自动识别当前查找是正向还是反向并返回对应字符, .
是Vim脚本的字符串连接操作符/<CR>
正向查找上一次匹配?<CR>
反向查找上一次匹配gn
匹配状态下的可视模式, 正向选中内容(光标不在最后一个字符时将选中匹配项的剩余字符, 光标在最后一个字符时将选中至下一个匹配项的第一个字符)
gN
匹配状态下的可视模式, 反向选中内容衍生:
gUgn
匹配内容转大写dgn
删除匹配内容cgn
修改匹配内容/pattern/e
设置匹配搜索结果时光标的位置在匹配内容的末尾, 可用 :h search-offset
查看更多值:%s//{string}/g
重复上一次匹配并替换(查找内容为空时会使用上一次匹配的模式),用于分步完成替换操作(先用
/
完成匹配):%s///gn
统计上一匹配的匹配数量, 标志位n抑制替换操作<C-r>/
输入上一次的查找模式~
在替换域中使用此符号, 则意味着使用上一次替换的替换域标志位
e
屏蔽错误提示(例如"找不到匹配的模式")标志位
&
重复上一次substitute命令的标志位\={script}
执行表达式脚本, 可在substitute命令中使用\=@{register}
调用寄存器内容, 可在substitute命令中使用\=submatch(0)-1
匹配项数字 -1
, 可用于HTML标签的h2替换为h1, h3替换为h2g&
相当于:%s//~/g
意为在当前文件里重复执行上一次替换(在忘记输入%
或g
的情况下使用)&
重复上一次替换命令:'<,'>&&
在选区中重复上一次替换命令
(第一个&
是重复上一次替换命令, 第二个&
是重复替换标志位,
需要两个&
是因为第一个&
并不会记住标志位)
:%s/\v(<man>|<dog>)/\={"dog":"man","man":"dog"}[submatch(1)]/g
交换替换
The dog bit the man
的 dog
和 man
, 其中 {}
是Vim脚本里的字典数据类型局限于一个窗口版本的快速恢复列表, 大多数快速恢复列表命令前加上
l
即可:lgrep
:lmake
:lopen
:lclose
:lnext
:lprev
:lwindow
一个Vim会话中只有一个快速恢复列表
:vimgrep //g %
将当前文件里上一次的匹配放进quickfix列表, %
为当前文本路径:grep
也可直接在Vim里调用外部grep程序, 运行结果会保存在quickfix列表里, 性能更好, 但支持不如vimgrep:copen
打开quickfix列表, 像Vim一样编辑:cclose
关闭quickfix列表, 像Vim一样编辑:cp[rev]
跳转到quickfix列表的上一项:cn[ext]
跳转到quickfix列表的下一项:vimgrep /{pattern} **/*.txt
查找当前目录下的所有txt文件:cfdo
对quickfix列表项目运行批处理, 有必要先 :set hidden
:set hidden
忽略未保存退出(切换缓冲区):cfdo update
保存所有quickfix列表文件(如果有更新的话):cfdo %s//{string}/g | update
替换保存二合一命令(|
是Vim的命令分隔符, 不是管道符号):[range] g[lobal] /{pattern}/ [cmd]
在整个文件(global命令的范围默认即为
%
)里对匹配到的行执行命令, 缺省的 cmd
为 print;
需要注意的是, 命令仍然支持指定范围, 所以
[cmd]
也可以看作 [range][cmd]
:v[global]
和:g[lobal]!
是:g[lobal]
的非匹配版本, 不匹配的行将执行cmd,v
指invert:g//d
删除所有匹配文本, 比如:g/\v\<\/?\w+\>/d
可删除所有HTML标签:g/TODO
收集TODO行qaq:g/TODO/yank A
清空寄存器a, 将所有TOOD收集进寄存器a
(使用大写A
是为了让每一行都能被追加进寄存器, 而不是覆盖):g/TODO/t$
收集TODO并复制到文件尾:g/{/ .+1,/}/-1 sort
排序CSS属性, 请注意.+1,/}/-1 sort
是此条命令的cmd部分
这条命令符合如下模式::g/{start}/ .,{finish} [cmd]
只将global用作匹配起点, 用.,{finish}
模式框选需要用cmd处理的部分:[range]copy {address}
复制内容到指定位置, 别名:t copyTo
:[range]move {address}
移动内容到指定位置, 别名:m
:'<,'>sort
排序选中行
grep的来历即为
:g/re/p
g是global, re是正则表达式, p是打印:[range]!{command}
执行Linux命令, 如果存在range, 则将以命令输出替换相关内容(过滤):r[ead] filename
将文本文件的内容输入到当前光标处:r[ead] !{command}
执行Linux命令并输入到当前光标处(空格可以省略):w[rite] !cat
这是read的相反命令, 将缓冲区写入shell命令, 注意空格不可省略, :w!
将改变语义为强制写入w | !node %
用 |
合并两条命令, 其中 %
会被替换为当前文件名jumps
查看跳转列表(jump list)<C-o>
反向遍历跳转列表<C-i>
或 <Tab>
正向遍历跳转列表changes
查看改变列表(change list)g;
反向遍历改变列表g,
正向遍历改变列表普通模式下
普通模式下
输入Ex命令时, 可用
q:
调出历史Ex命令行窗口, 回车执行当前行命令普通模式下
q/
调出历史查找命令行窗口, 回车执行当前行命令输入Ex命令时, 可用
<C-f>
将当前输入的内容切换到命令行窗口编辑创建
.vim
文件, 可以用于Ex命令的批处理, 在批处理中不需要在语句首使用::source batch.vim
在打开的文件中执行批处理=:args
显示参数列表(当 vim *.txt
一次性打开多个文件时, 可以看到参数列表里有多个文件):n[ext]
移动到下一个文件:pre[vious]
移动到上一个文件:first
移动到首个文件:argdo source batch.vim
对参数列表里的每一个文件执行batch.vim批处理Vim脚本(用于宏)
:let i=0
赋值:echo i
打印:let i+=1
递增<C-r>=i<CR>
在插入模式下用表达式寄存器输入i的值:echo @a
打印宏内容:let @a=substitute(@a, 'old', 'new', 'g')
赋值替换宏内文本:set
或 :se
显示所有修改过的配置:set all
显示所有配置项:set option?
显示option的值:set option!
取消option的值:set option&
重置option的值为默认值:set nooptions
取消option的值:ver
显示 vim 的信息:setlocal
只对当前缓冲区生效的配置:bufdo setlocal
对当前打开的所有缓冲区生效的配置:windo setlocal
对当前打开的所有窗口生效的配置:set nu
显示绝对行号 number:set nonu
取消显示绝对行号 number:set relativenumber
显示相对行号(会覆盖绝对行号):n
前往第n行(相当于 nG
, ngg
, nH
):set ic
或 :set ignorecase
使查找命令不区分大小写:set noic
使查找命令区分大小写 no ignore cases:set smartcase
智能大小写敏感性(当出现大写字符时, 自动敏感):set hls[earch]
高亮匹配内容:set nohls[earch]
关闭高亮:noh[lsearch]
临时关闭高亮(至下一次搜索):set incsearch
在搜索输入关键字时, 就匹配第一个结果:set nowrapscan
关闭搜索时找不到内容就自动从文件头部继续搜索的特性:set ft=html
设置文件类型为html(file type):set history=200
将历史命令保存上限设置为200条:set paste
进入paste模式, 该模式下autoindent等妨碍粘贴的选项将被关闭(在gVim等GUI版本里, 无需设置paste, 粘贴会被自动识别, 不会打乱文本)
:set nopaste
退出paste模式:set pastetoggle=<f5>
将paste模式的开关设置为F5:so[urce] {file}
执行Vim脚本, 一般用来更新.vimrc的修改:so[urce] $MYVIMRC
跨平台的vimrc更新命令:so%
执行当前编辑的Vim脚本:edit $MYVIMRC
跨平台的vimrc文件编辑命令:set directory=$HOME/.vim/swap//
设置交互文件的保存路径(默认为当前文件的位置):set noswapfile
关闭交互文件功能:set undofile
启动持久性撤销(退出文件后仍然保留编辑历史记录)在
.vimrc
里启动持久性撤销并设置撤销文件的保存路径set undofileif !isdirectory("$HOME/.vim/undodir") call mkdir("$HOME/.vim/undodir", "p")endifset undodir="$HOME/.vim/undodir"
:h[elp] {keyword}
在帮助文件里查找关键字:h[elp] {keyword} <C-d>
输入一个不完整的关键字, 显示帮助文件里所有包含此关键字的标签.