VIM 实用技巧

:h vimtutor:进入 VIM 内置文档
vim -u NONE -N:使用 VIM 的出厂配置;-u NONE 标志让 VIM 在启动时不加载 vimrc,这样,定制项就不会生效,插件也会被禁用。
当不用加载 vimrc 文件的方式启动时,VIM 会切换到 vi 兼容模式,这将导致很多有用的功能被禁用,-N 标志则会使能 nocompatible 选项,防止进入 vi 兼容模式。

认识 . 命令

. 命令是一个微型的宏。

. 命令可以让我们重复上次的普通模式命令;从进入插入模式的那一刻起(例如,输入 i),直到返回普通模式时为止(输入),VIM 会记录每一个按键操作。做出这样一个修改后再用 . 命令的话,它会将重新执行所有这些按键操作。

>G:会增加从当前行到文档末尾处的缩进层级

@::命令可以重复执行任意Ex命令(即在命令模式下输入 : 后输入的命令)
&:命令可以重复上次的 :substitute 命令(它本身也是一条 Ex 命令)

:set hls:将查找到的内容高亮显示;:noh:取消高亮显示
u 键会触发撤销命令,它会撤销最新的修改。在 VIM 中可以自己控制撤销命令的粒度。从进入插入模式开始,直到返回普通模式为止,在此期间输入或删除的任何内容都被当成一次修改。因此,只要控制好对 键的使用,就可使撤销命令作用于单词、句子或段落。

在插入模式中移动光标会重置修改状态。

撤销命令会回退从进入插入模式到退出此模式期间输入或删除的全部字符时,注意,如果在插入模式中使用了 、、、 这些光标键,将会产生一个新的撤销块。可以把这想象为先切换回普通模式,然后用 h、j、k 或 l 命令对光标进行了移动,唯一区别是没有退出插入模式。这也会对 . 命令的操作产生影响。

反向删除:普通模式下,当光标位于一个单词的末尾时,可以使用 dbx 删除当前单词。
正向删除:普通模式下,当光标位于一个单词的末尾时,可以使用 bdw 删除当前单词。
不论光标在单词的哪个字母上都可以使用 daw (delete a world)删除当前单词和后面的一个空格。

用次数做简单的算数运算

和 命令分别对数字执行加和减操作。在不带次数执行时,它们会逐个加减,但如果带一个次数前缀,那么可以用它们加减任意整数。例如,如果把光标移动到字符 5 上,执行 10 就会把它变成 15。如果光标不在数字上,那么 命令将在当前行正向查找一个数字,如果找到了,它就直接跳到那里并将这个数字加一。

VIM 把以 0 开头的数字解释为八进制,而不是十进制。可以将 set nrformats= 加入 vimrc 中,这会让 VIM 把所有数字都当成十进制,不管它们是不是以 0 开头的。

操作符 + 动作命令 = 操作
d{motion} 命令可以对一个字符(dl)、一个完整单词(daw)或一整个段落(dap)进行操作,它作用的范围由动作命令决定。c{motion}、y{motion} 以及其他一些命令也类似,它们被统称为操作符。可以用 :h operator 来查阅完整的列表。

VIM 的语法只有一条额外规则:当一个操作符命令被连续调用两次时,它会作用于当前行。所以 dd 删除当前行,而 >> 缩进当前行

VIM 的操作符命令

命令用途
c修改
d删除
y复制到寄存器
g~反转大小写
gu转换为小写
gU转换为大写
>增加缩进
<减小缩进
=自动缩进
!使用外部程序过滤 {motion} 所跨越的行

插入模式

插入模式下,使用 删除前一个字符; 删除前一个单词; 删至行首
插入模式下,可以使用 或 <C-[> 切换回普通模式,使用 切换到插入-普通模式(可以在插入模式下执行一次普通模式下的命令)
{register},将指定寄存器中的内容粘贴到光标所在位置,其中 {register} 是想要插入的寄存器的名字
= 表示表达式寄存器,在插入模式中,输入 <C-r>= 就可以访问这一寄存器。这条命令会在屏幕的下方显示一个提示符,可以在其后输入要执行的表达式。输入表达式后敲一下 (回车),VIM 就会把执行的结果插入文档的当前位置了。

只要知道某个字符的编码,就可以让Vim插入该字符,我们可以用这种方式插入任意字符。要根据字符编码插入字符,只需在插入模式中输入 <C-v>{code} 即可,其中 {code} 是要插入字符的编码。
Vim接受的字符编码共包含3位数字。例如,假设想插入大写字母“A”,它的字符编码是65,因此需要输入 065 。
然而,如果想插入一个编码超过3位数的字符该怎么办?例如,Unicode基本多文种平面(Unicode Basic Multilingual Plane)的地址空间最大会有65 535个字符。解决方法是用4位十六进制编码来输入这些字符,即输入 ·u{1234}· (注意数字前的 u )。假设想插入字符编码为00bf的反转问号(“¿”),只需在插入模式中输入 u00bf 即。
如果你想知道文档中任意字符的编码,只需把光标移到它上面并按 ga 命令,然后屏幕下方会显示出一条消息,分别以十进制、十六进制和八进制的形式显示出其字符编码。
另外,如果 命令后面跟一个非数字键,它会插入这个按键本身代表的字符。

用二合字母插入非常用字符
二合字母用起来很方便。在插入模式中,只需输入 <C-k>>{char1}{char2} 即可。
例如,左右书名号《和》分别以二合字母<<及>>表示,普通分数(或常用分数)½、¼和¾则分别以二合字母12、14和34来表示。
用命令 :digraphs 可以查看可用的二合字母列表,不过该命令的输出不太好阅读。也可以用 :h digraph-table 查看另一个更为有用的列表。

虚拟替换模式可由 gR 命令触发,它会把制表符当成一组空格进行处理而不是一个字符。
假设把光标移到一个占屏幕8列宽的制表符上,然后切换到虚拟替换模式,在输入前7个字符时,每个字符都会被插入制表符之前;最后,当输入第8个字符时,该字符将会替换制表符。

可视模式

gv 命令可以重新选择上次的高亮区域
切换选区的活动端:高亮选区的范围由其两个端点界定。其中一端固定,另一端可以随光标自由移动,可以用 o 键来切换其活动的端点。在定义选区时,如果定义到一半,才发现选区开始的位置不对,此时用这个键会很方便,不用退出可视模式再从头开始,只需按一下 o ,然后重新调整选区的边界即可。

在可视模式中执行完一条命令后,会返回到普通模式,并且在可视模式中选中的文本范围也不再高亮显示了。
当一条可视模式命令重复执行时,它会影响相同数量的文本
可视模式下的 U 命令有一个等效的普通模式命令:gU{motion},如果用此命令做第一处修改,就可以用点范式完成后续的修改。

命令行模式

在按下 : 键时,Vim会切换到命令行模式。出于历史原因,在命令行模式中执行的命令又被称为 Ex 命令。
用行号作为地址:如果输入一条只包含数字的 Ex 命令,那么 Vim 会把这个数字解析成一个地址,并把光标移动到该数字指定的行上。
:$:文件最后一行,:.:代表当前行地址,:%:代表当前文件中的所有行,:0:虚拟行,位于文件第一行上方。
:copy(:co/:t) 命令及其简写形式 :t 可以把一行或多行从文档的一部分复制到另一部分,:move(m) 命令则可以把一行或多行移动到文档的其他地方。
:[range]copy {address}:将 range 行的内容复制到 address 行的下方(省略 range 则表示当前行)
重复上次的 Ex 命令只需按 @: 即可。

:bn[ext] 可以在列表中逐项正向移动;用 :bp[revious] 进行反向移动

: 寄存器总是报存着最后执行的命令行命令。在运行过一次 @: 后,后面就可以用 @@ 命令来重复它。

把当前单词插入命令行:在命令行模式下, 映射项会复制光标下的单词并把它插入命令行中;插入光标下的字串:

命令行窗口就像是一个常规的 VIM 缓冲区,只不过它的每行内容都对应着命令历史中的一个条目;在普通模式下使用 q: 命令可以调出命令行窗口。
当处于命令行模式下时,可以使用 映射项切换到命令行窗口中,此前已经输入命令行上的内容仍然会得以保存。
q/:打开查找命令历史的命令行窗口;q::打开 Ex 命令历史的命令行窗口。

运行 shell 命令:在命令行模式中,给命令加一个 ! 前缀,就可以调用外部程序。
:!{cmd}:执行一次性命令;:shell:启动一个交互的 shell 会话,用 exit 可以退出此 shell 并返回 VIM。

管理多个文件

文件是存储在磁盘上的,而缓冲区(Buffer)则是存在于内存中。当 VIM 打开一个文件时,该文件的内容被读取入一个具有相同名字的缓冲区。刚开始,缓冲区的内容和文件的内容完全相同,但当对缓冲区做出修改时,二者的内容就会出现差别。如果决定保留这些修改,就可以再把缓冲区的内容写回到文件里。

:ls:命令会列出所有被载入到内存中的缓冲区的列表,:bn[ext]:命令可以切换到列表的下一个缓冲区。%:表示哪个缓冲区在当前窗口中可见,#:代表轮换文件;<C-^> 可以在当前文件和乱换文件间快速切换;
:bp[rev]:bn[ext] 可以在列表中反向或正向移动,每次移动一项;而 :bf[irst]:bl[ast] 则分别跳到列表的开头和结尾。
:bd[elete] number 可以删除缓冲区(number 为缓冲区编号,删除一个缓冲区并不会影响缓冲区所关联的文件,而只是简单地把该文件在内存中的映像删掉)

:args:显示参数列表,参数列表记录了在启动时作为参数传递给 VIM 的文件列表;如果想在列表中增加几个文件,可以在 args 参数后增加文件名即可(:args a.txt b.log c.md);也可以使用通配符打开指定类型文件,* 符合用于匹配 0 个或多个字符,但它的范围仅仅局限于指定的目录,而不会递归其子目录,** 通配符也匹配 0 个或多个字符,但它可以递归进入指定目录的子目录(:args *.*:args **/*.js:args **/*.*)
:argdo:可以在参数列表中的每个文件上执行一条 Ex 命令;
用反引号结构指定文件,如 :args \cat .filename``,VIM 会在 shell 中执行反引号括起来的命令,然后再把 cat 命令的输出作为 :args 命令的参数。

管理隐藏缓冲区:在当前缓冲区中作出修改后,:ls 输出内容在当前缓冲区前会有一个 + 号,表示这个缓冲区被修改过了,如果此时切换缓冲区,VIM 会弹出一条错误信息,说当前缓冲区有未保存的改动,在切换缓冲区命令后加一个 !,叹号会强制 VIM 切换缓冲区,即使当前缓冲区有未保存的修改,也会继续切换;如果现在运行 :ls 命令会发现当前缓冲区被标记为 a,表示它当前是活动缓冲区(active),而上一个缓冲区则被标记为 h,表示它是一个隐藏缓冲区(hidden)。
在退出时处理隐藏缓冲区:当一个缓冲区被隐藏后,VIM 允许我们像往常一样工作。当想关闭(:q[uit])编辑会话时,VIM 就会提醒我们某个缓冲区中有未保存的修改,VIM 会把第一个有改动的隐藏缓冲区载入当前窗口,这样我们就可以决定如何处理它。如果要保留修改,可以执行 :w[rite] 命令把缓冲区保存到文件,如果想摒弃此修改,可以执行 :e[dit]! 重新从磁盘读取此文件,这会用文件的内容覆盖缓冲区的内容。
如果想退出 VIM 而不想对未保存的修改进行检查,可以执行 qa[ll]! 命令;如果想保存所有有改动的缓冲区而无需逐个检查,可以用 :wa[ll] 命令。

分割窗口:s 水平分割窗口,新窗口显示当前缓冲区;v 垂直分割窗口,新窗口显示当前缓冲区;:sp[lit] {file}:水平分割窗口,在新窗口载入 {file};:vsp[lit] {file}:垂直分割窗口,在新窗口载入 {file}。
在窗口间切换:w:在窗口间循环切换;h:j:k:l:
关闭窗口::clo[se] 或 c:关闭活动窗口;:on[ly] 或 o:只保留活动窗口,关闭其他所有窗口。
=:使所有窗口等宽、等高;:最大化活动窗口高度;|:最大化活动窗口宽度;[N]:把活动窗口的高度设为 N 行;[N]|:把活动窗口的宽度设为 N 列。

在 VIM 中可以用标签页把窗口组织到一系列工作区里,标签页是可以容纳一系列窗口的容器。
:lcd[path] 命令可以设置当前窗口的本地工作目录;
打开及关闭标签页::tabe[dit] {filename}:在新标签页中打开 {filename} ,如果省略 {filename},VIM 会创建一个新标签页,里面包含一个空缓冲区;T:把当前窗口移到一个新标签页;:tabc[lose]:关闭当前标签页及其所有窗口;:tabo[nly]:只保留活动标签页,关闭所有其他标签页。
在标签页间切换:标签页的编号从 1 开始,可以用 {N}gt 命令在标签页间切换,如果省略了数字前缀,则会跳到下一个标签页。gT 命令跳转到上一个标签页。
:tabn[ext] {N}{N}gt:切换到编号为 {N} 的标签页;:tabn[ext]gt:切换到下一标签页;:tabp[revious]gT:切换到上一标签页。
重排标签页:tabmove {N} 可以重新排列标签页。当 N 为 0 时,当前标签页会被移动到开头,如果省略了 N,当前标签页会被移动到结尾。

打开及保存文件

:edit {file} 命令打开文件:它能以文件路径(绝对路径或相对路径)打开任何文件,若传入的 {file} 是一个目录,则会打开文件管理器窗口;:pwd :打印 VIM 当前工作目录。
相对于活动文件目录打开一个文件::edit %<Tab>% 表示活动缓冲区的完整文件路径,按 会将其展开,使之显示为活动缓冲区的完整文件路径;:edit %:h<Tab>:h 修饰符会去除文件名,但保留路径中的其他部分,此例中 :h<Tab> 会被展开为当前文件所在目录的路径。
使用 :find 打开文件:此命令允许通过文件名打开一个文件,但无需输入文件的完整路径,要利用此功能,首先需要配置 'path' 选项。
配置 'path' 选项:'path' 选项允许我们指定一些目录,当调用 :find 命令时,VIM 会在这些目录中进行查找。如 :set path+=app/** 递归查找 app 目录下的所有文件。
把文件保存到不存在的目录中::edit {file} 命令一般用于打开一个已存在的文件。如果指定了一个不存在的文件路径,那么 VIM 就会创建一个新的空白缓冲区。如果此时按 ,就会看到该缓冲区被标识为”新文件“( 命令用于显示当前文件的文件名及状态),随后,当执行 :write 命令时,VIM 就会尝试将此缓冲区的内容写到创建该缓冲区时所指定的文件路径中。如果执行时所指定的文件路径中包含尚未存在的目录,当把缓冲区的内容写入文件时,VIM 会显示出一条出错信息,在这种情况下,可以调用外部的 mkdir 命令做出补救::!mkdir -p %:h :write

用动作命令(motion)在文档中移动

hjkl 命令会按照实际行进行移动,而 gj gk 等会按照屏幕行进行移动,即在所有操作实际行的动作前加上 g 就可以操作屏幕行。(:set number 后显示行号的是实际行,若一行内容过长显示不下换行后显示的就是屏幕行)

基于单词移动:w:正向移动到下一单词的开头;b:反向移动到当前单词/上一单词开头;e:正向移动到当前单词/下一单词结尾;ge:反向移动到上一单词结尾。

单词(word)与字串(WORD):单词由字母、数字、下划线或其他非空白字符的序列组成,单词间以空白字符(包括空格、Tab、回车)分隔;字串由非空白字符序列组成,之间以空白字符分隔。

f{char}:正向移动到下一个 {char} 所在之处;F{char}:反向移动到上一个 {char} 所在之处;t{char}:正向移动到下一个 {char} 所在之处的前一个字符上;T{char}:反向移动到上一个 {char} 所在之处的后一个字符上;(t 命令可以结合 d 命令使用,如 dt{char} 删除光标处到 {char} 的前一个字符,不包括 {char};df{char}:删除光标处到 {char} 字符,包括 {char})

文本对象允许操作括号、被引用的文本、HTML 标签以及其他文本中的常见结构,文本对象就是基于结构定义的文本区域。
VIM 的文本对象由两个字符组成,第一个字符永远是 i(inside) 或 a(around/all)。以 i 开头的文本对象会选择分隔符内部的文本,而以 a 开头的文本对象则会选择包括分隔符在内的整个文本。vit 表示选择一对 XML 标签内部内容。
每当在命令语法里看到 {motion} 时,说明可以在这个地方使用文本对象。常见的包括:d{motion}c{motion}(删除指定的文本后进入插入模式) 和 y{motion}
VIM 的文本对象分为两类:一类是操作分隔符的文本对象,如 i)i"it;另一类用于操作文本块,如单词、句子和段落。

文本对象选择范围
iw当前单词
aw当前单词及一个空格(在删除一行句子中间的一个单词时有用,不会导致删除后出现两个空格)
iW当前字串
aW当前字串及一个空格
is当前句子
as当前句子及一个空格
ip当前段落
ap当前段落及一个空格

设置位置标记,以便快速跳回:m{a-zA-Z} 命令会用选定的字母标记当前光标所在位置。小写位置标记只在每个缓冲区里局部可见,而大写位置标记则全局可见。
\{mark}:跳转到一个位置标记上,例如mm标记,`m` 跳转。
VIM 的自动位置标记

位置标记跳转到
``当前文件中上次跳转动作之前的位置
`.上次修改的地方
`^上次插入的地方
`[上次修改或复制的起始位置
`]上次修改或复制的结束位置
`<上次高亮选区的起始位置
`>上次高亮选区的结束位置

% 命令允许在一组开、闭括号间跳转。

在文件间跳转

VIM 会记录跳转前后的位置, 就像后退按钮一样, 就像前进按钮一样。
:jumps 命令可以查看跳转列表的内容。
[count]G 命令直接跳转到指定行也会被当成一次跳转,但每次向上或向下移动一行则不算。面向句子和段落的动作都算跳转,但面向字符和单词的动作则不算。

命令用途
(/)跳转到上一句/下一句开头
{/}跳转到上一段/下一段开头
H/M/L跳转到屏幕最上方/中间/最下方
gf跳转到光标下的文件名(需用 :set suffixesadd+=.rb 命令进行设置)
<C-]>跳转到光标下关键字的定义处

遍历改变列表:每当对文档做出修改后,VIM 都会记录当时光标所在位置。VIM 会在编辑会话期间维护一张表,里面记载了对每个缓冲区所做的修改,此表就是所谓的改变列表。
:changes 命令可以查看其内容,VIM 为每次修改都记录了行号和列号,可以用 g;g, 命令反向或正向遍历改变列表。gi 命令可以回到上次插入模式退出的位置并进入插入模式继续编辑。

寄存器

复制与粘贴

VIM 不使用单一的剪贴板进行剪贴、复制、粘贴,而是为这些操作提供了多组寄存器。
引用一个寄存器:可以通过给命令加 "{register} 前缀的方式指定要用的寄存器。若不指明,VIM 将缺省使用无名寄存器。
VIM 也提供了剪贴、复制、粘贴的 Ex 命令,如 :delete c 把当前行剪贴到寄存器 c,然后再执行 :put c 命令将其粘贴至当前光标所在行之下。

无名寄存器(""
xsdcy 命令均会覆盖无名寄存器的内容
复制专用寄存器("0
仅当使用 y 命令才会被赋值
有名寄存器("a-"z
VIM 提供了一组以 26 个英文字母命名的有名寄存器;用小写字母引用有名寄存器,会覆盖该寄存器的原有内容,而用大写字母,则会将新内容添加到该寄存器的原有内容之后。
黑洞寄存器
黑洞寄存器是个有去无回的地方,可用下划线引用它。例如 "_d{motion} 命令可以删除文本且不报存任何副本,当只想删除文本却不想覆盖无名寄存器中的内容时很有用。
系统剪贴板("+
"+p 或在插入模式下输入 + 命令可以将系统剪贴板中的内容粘贴到 VIM 内部。
表达式寄存器("=
当从表达式寄存器获取内容时,VIM 将跳转到命令行模式,并显示提示符 =。这时,可以输入一段 VIM 脚本表达式并回车执行,如果返回的是字符串吗,VIM 将使用它。
其他寄存器
"%:当前文件名
"#:轮换文件名
".:上次插入的文本
"::上次执行的 Ex 命令
"/:上次查找的模式
插入模式下输入 {register} 可以插入寄存器中的内容到光标前
当要粘贴的内容来自于面向行的寄存器时,pP 将文本粘贴至当前行的上一行或下一行;gpgP 将文本粘贴在当前行的之前或之后

与系统剪贴板进行交互
:set autoindent 设置自动缩进
:set paste 激活 paste 选项

宏的读取与执行:使用宏可以把一段修改序列录制下来,用于之后的回放。
q 键是开始录制和结束录制的命令;使用 q{register} 开始录制并指定一个用于保存宏的寄存器;用 [count]@{register} 命令执行指定寄存器的内容,及回放宏,也可以用 @@ 来重复最近调用过的宏。

录制宏的过程中如果漏掉了关键步骤,此时没必要从头开始重新录制,可以在现有的宏的结尾附加额外的命令。(小写字母寄存器会覆盖原有内容,而大写字母寄存器会追加内容)
:argdo 命令可以对参数列表中的所有缓冲区执行一条 Ex 命令,例如,:argdo normal @a
编辑宏的内容:将寄存器中保存的宏粘贴在缓冲区中修改后再复制到寄存器中。

模式

在 VIM 的查找域中,某些字符的缺省具有特殊含义,当只想按原义匹配一段文本时,这一特点将导致问题复杂化,为此,需掌握如何使用 very magic 原义开关,一举屏蔽这些特殊含义。
:setignorecase 命令将会使查找模式不区分大小写(此设置具有副作用,会影响 VIM 关键字自动补全的行为)
每次查找时设置大小写敏感性:通过使用元字符 \c(忽略大小写) 与 \C(不忽略大小写),可以覆盖 VIM 缺省的大小写敏感性设置。若在某个查找模式中使用了两者中的某一个,ignorecase 的值将被这次查找忽略。

这两个元字符可以出现在模式的任意位置。假设已经输入了完整的模式,却发现需要按区分大小写的方式进行查找。此时,只需在模式的结尾加上 \C,该元字符就会作用于它前面的所有文本。

当启用了 smartcase 选项后,无论何时,只要在查找模式中输入了大写字母,ignorecase 设置就不再生效了。即如果模式全是由小写字母组成的,就会按照忽略大小写的方式进行查找,但是只要输入了一个大写字母,查找方式就会变成区分大小写的了。
按正则表达式查找时,使用 \v 模式开关:用 \v 模式开关来统一所有特殊符号的规则。该元字符会激活 very magic 搜索模式,即假定除下划线、大小写字母及数字之外的所有字符都具有特殊含义,它们不用转义。如 /#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\)/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})
按原义查找文本时,使用 \V 原义开关:使用 very nomagic 原义开关,可以消除附加在 .*? 等大多数字符上的特殊含义,使用 \V 会使得其后的模式中只有反斜线有特殊的意义。如 / \Va.k.a.

界定单词边界:在 very magic 搜索模式下,用 <> 符号表示单词定界符。而在magic、nomagic 以及very nomagic 搜索模式下,则必须要将它们转义
使用圆括号,但不捕获其内容:在圆括号前面加上 % ,指示 Vim 不要将括号内的内容赋给寄存器 \1,就像这样:/\v%(And|D)rew Neil
一个匹配的边界通常对应于一个模式的起始与结尾。但我们可以使用元字符 \zs\ze 对匹配进行裁剪,使其成为这个完整模式的一个子集)。
元字符 \zs 标志着一个匹配的起始,而元字符 \ze 则用来界定匹配的结束。将二者相结合,我们可以定义一个特殊的模式,它们可以让我们定义一个模式匹配一个较大的文本范围,然后再收窄匹配范围。

查找

当我们执行一次查找时,Vim 会从当前光标位置开始向下扫描,停在所找到的第一处匹配上。如果Vim 扫描到文档结尾仍未找到目标,会提示“已查找到文件结尾,再从开头继续查找”。如果只想在当前光标位置至文档结尾的范围内查找,而不想绕回文档继续查找的话,可以关闭 wrapscan 选项
当我们使用 / 键执行一次查找时,Vim 将进行正向扫描。而如果是用 ? 键调出查找提示符的话,Vim 则会进行反向查找。
n 命令用于跳转到下一处匹配,而 N 命令则用于跳转到上一处匹配。
/<CR>?<CR> 可以改变查找的方向

高亮查找匹配::se hls
取消高亮::set noh[lsearch](:noh)
在执行查找前预览第一处匹配(即时的反馈体验)::set incsearsh
根据预览结果对查找域自动补全:<C-r><C-w>
统计当前模式的匹配个数::%s///gn;实际上,我们调用的是 :substitute 命令,但标志位 n 会抑制正常的替换动作。该命令不会对每处匹配进行替换,而是简单地统计匹配的次数,并将结果显示到命令行上。此处我们将查找域留空,旨在让 Vim 使用当前的查找模式。替换域(由于标志位 n 的缘故)不管怎样都将会被忽略,因此也可以将其留空。
将光标偏移到查找匹配的结尾:/{char}/e<CR>,可用查找偏移把光标定位于距离某个匹配的起始或结尾一定步长的位置;假设一开始并没有用偏移执行查找命令,而是在敲了若干次 n 之后,才发现最好将光标移至匹配的结尾,可以简单地运行 //e<CR>。当我们把查找域留空时,Vim 将重用上一次的查找模式,因此,该命令将使用偏移重复上一次查找。每当执行查找命令时,光标总会被定位于匹配的首字母上。
查看利用查找历史:q/,用 q/ 调出命令行窗口。此窗口与一个常规的 Vim 缓冲区差不多,不过它的内容是查找历史,每行显示一条
查找选中的文本:y/<C-r>"<CR>,首先,y 命令会复制当前高亮选区的文本。然后,/<C-r>"<CR> 调出查找提示符,并将无名寄存器的内容粘贴进来。最后,执行查找命令。

替换(substitute)

:substitute 命令很复杂,除了要提供查找的模式以及替换字符串外,还要指定执行的范围。另外,作为可选项,我们还可以通过标志位来调整该命令的行为。

substitute 命令语法::[range]s[ubstitute]/{pattern}/{string}/[flags]
利用标志位调整 substitute 命令的行为:标志位 g 使得 subsititute 命令可在全局范围内执行,即可以修改一行内的所有匹配,而不仅仅是第一处匹配。标志位 c 让我们有机会可以确认或拒绝每一处修改。标志位 n 会抑制正常的替换行为,即让 Vim 不执行替换操作,而只是报告本次 substitute 命令匹配的个数。
当我们执行 substitute 命令时,如果在当前文件中没有匹配到该模式,Vim 会提示错误信息“E486: 找不到模式”,标志位 e 专门用于屏蔽这些错误提示。标志位 & 仅仅用于指示 Vim 重用上一次 substitute 命令所用过的标志位。

替换域中的特殊字符(:h sub-replace-special)

符号描述
\r插入一个换行符
\t插入一个制表符
\\插入一个反斜杠
\1插入第 1 个子匹配
\2插入第 2 个子匹配(以此类推,最多到 \9
\0插入匹配模式的所有内容
&插入匹配模式的所有内容
~使用上一次调用 :substitute 时的{string}
\={VIM script}执行{VIM Script} 表达式;并将返回的结果作为替换{string}

在文件范围内查找并替换每一处匹配:在缺省情况下,substitute 命令仅仅作用于当前行,而且只会修改第一处匹配。为了在整个文件的范围内修改每一处匹配,我们必须指定范围,并使用标志位 g 。如果我们在 substitute 命令的开头加上前缀 %,它就会在文件的每一行上执行了。(:%s/going/rolling/g

手动控制每一次替换操作:有时需要先观察每一处匹配,再决定是否进行替换。为了做到这一点,可以用标志位 c 控制 :substitute 命令的行为。(:%s/content/copy/gc)

引入标志位 c 后,Vim 会对每处匹配结果提示“替换为copy ?”,可以按 y 键,完成这次修改,或者按 n 键,跳过这一次修改。无论采用哪种方式,Vim 都会执行我们的决定,并移到下一匹配处再次提示。

Vim 会体贴地为我们提示所有的选项“y/n/a/q/l/E/Y”。下表展示了每种答案的含义:

答案用途
y替换此处匹配
n忽略此处匹配
q退出替换过程
l“last” —— 替换此处匹配后退出
a“all” —— 替换此处与之后所有的匹配
向上滚动屏幕
向下滚动屏幕

重用上次的查找模式:将 substitute 命令的查找域留空,意味着 Vim 将会重用上次的查找模式。在命令行中输入 <C-r>/ ,即可把上次的查找内容粘贴进来。

用寄存器的内容替换:实际上,不必手动输入完整的替换字符串。如果某段文本已在当前文档中出现,我们可以先把它复制到寄存器,再通过传值或引用的方式将寄存器的内容应用至替换域。
将替换域留空,意味着 substitute 命令会用空的字符串替换每一处匹配。换句话说,所有的匹配都被删除了。
传值:通过输入 <C-r>{register},可以将寄存器的内容插入到命令行。(:%s//0/g)
引用:假设已经复制了多行文本,并存放于寄存器 0 中。我们现在的目标是在 substitute 命令的替换域中使用这段文本。通过运行以下命令,可以做到这一点::%s//\=@0/g;替换域中出现的 \= 将指示 Vim 执行一段表达式脚本。在Vim 脚本中,可以用 @{register} 来引用某个寄存器的内容。

重复上一次substitute 命令

在整个文件范围内重复面向行的替换操作:当执行某个替换时忘记使用 %,输入 g&(参见:h g&),即可在整个文件的范围内重复这条命令。
修正 substitute 命令的执行范围:gv 命令会激活可视模式,并重新将上次被选中的文本高亮起来。而当在可视模式下按输入 : 时,表示范围的 :’<,’> 将被预先填充在命令行上,它限定了下一条命令只会在被选中的行上执行。
:&& 命令:前一个 & 作为 Ex 命令 :& 的组成部分,用作重复上一次的 :substitute 命令(参见:h :&),而第二个 & 则会重用上一次 :s 命令的标志位。

global 命令

自动补全

ignorecase 选项被启用后,无论是大写字母还是小写字母,Vim 的查找命令都对它们一视同仁,但这样做也有副作用,即在自动补全时也会忽略大小写。可以通过启用 infercase 选项来修正这一行为
通过 <C-p><C-n> 这两个组合键,我们不仅可以在插入模式下触发 Vim 的自动补全,而且还可以用它们在补全列表中反向或正向选择。

触发 VIM 自动补全的方法总结

命令补全类型
<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>全能补全

可供弹出式菜单使用的命令

按键操作作用
<C-n>使用来自补全列表的下一个匹配项
<C-p>使用来自补全列表的上一个匹配项
<Down>选择来自补全列表的下一个匹配项
<Up>选择来自补全列表的上一个匹配项
<C-y>确认使用当前选中的匹配项
<C-e>还原最早输入的文本(从自动补全中 exit)
<C-h>从当前匹配项中删除一个字符
<C-l>从当前匹配项中增加一个字符
{char}中止自动补全并插入字符 {char}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值