跳过正文

《VIM 实用技巧》笔记

·568 字·3 分钟
Vim Tools
Yan Zhitao
作者
Yan Zhitao
A Web/GIS Developer, and a runner

这貌似是 2016 年上学的时候就写的笔记了,整理一下放到网站上,充实下内容 hhhh

图书馆居然找到一本 Vim 的书,是 Drew Neil 的《Vim 实用技巧》,想想刚开始用 Vim 痛不欲生的日子,(当然现在也是,只不过成了“活着就好”的状态,2333)然后考完试就立刻借来啦,Vim 真的是贼好用,当然该开始学的时候确实痛苦,浏览器装个 Vimium 扩展, 简直爽的不要不要的,有了 Vim ,还要鼠标干嘛? 看了一下这本书有 20 章,打算花 15 天左右慢慢看完,同时用 GVim(windows 的 Vim )把笔记记下来

“.“的使用
#

结识 . 命令
#

. 命令可以让我们重复上次的修改,他是 Vim 中最为强大的多面手。

这里写几个书上的例子。

  • 光标在 Line 的位置上时,按下 x 会删除一个字符,之后按 . 就会重复上次操作,继续删除一个字符。
// before
Line one
// after
e one
  • >G 命令会给当前行到文档末尾添加一个缩进,在第二行使用 >G 命令后,按 j 跳到下一行,接着再按下 . “重复上次修改”,就为每行文本添加缩进。
// before
Line one
Line two
Line three
Line four
// after
Line one
        Line two
                Line three
                        Line four

不要自我重复
#

行尾添加内容这样很简单的操作,Vim 提供了一个专门的命令可以把两步操作合成为一步。

假设有这样的一个代码片段:

var vimIsGood = "Vim da fa is good";
var mdzz = 1;
var vim = vimIsGood + mdzz;

现在我想要给每行代码的结尾补上分号,一般的步骤是先按下 $ 将光标移动到行尾,接着按下 a 切换到输入模式,然后按下 ; 输入漏掉的分号,再按下 Esc 退出输入模式。

  • 减少无关的移动

    a 命令是在当前光标之后添加内容,而 A 是在当前的行尾添加内容。 对于上面的代码,只需要执行一次 A;<Esc> 之后,然后就可以愉快的使用命令 j. 把每行代码末尾添加分号。

var vimIsGood = "Vim da fa is good";
var mdzz = 1;
var vim = vimIsGood + vim;

以退为进
#

假设有这样一段代码

var foo = "(" + argument1 + "," + argument2 + ")";

看起来有点辣眼睛,因为上面的代码是黏成一片的,如果在 + 号前后都加上一个空格,看起来会舒服不少。

光标在代码开头处,按下 f+ 将光标移动到 + 处,然后按下 s 删除当前的 + 号并切换到输入模式,输入 + ,在之前的 + 号出左右加上空格,然后按下 Esc 退出输入模式。

接下来的工作就 so easy 了,按下 ; 跳转到上次 f 命令所查找的字符,然后按下 . 来重复上次操作,简单来说就是连着按下 ;. 就可以在后面的 3 个 + 号左右都加上空格了。

操作完成后看起来一下舒服了不少。

var foo = "(" + argument1 + "," + argument2 + ")";

查找并手动替换
#

Vim 提供了 :substitute 命令来进行查找替换 :s/target/replacement 方便是方便,但是遇上多义词就有点不合适了,比如:“我在方便的时候想方便一下”这句话,把方便都换为“撒尿”就不合适了。

  • 写到这里好像遇到一个尴尬的问题,Vim 好像并不适合中文查找替换。用英文代替吧,毕竟不用中文撸码子。

比如有这样一段话

We'are waiting for content before .... If you are content with this, ... as soon
as we have the content..

刚开始,把光标移到 “content” 上,然后用 _ 命令进行查找,按下 _ 后,所有出现这个词的地方都会高亮显示。

当光标位于 “content” 开头时,接着按下 cw 删除光标位置到单词结尾间的字符,并进入插入模式,然后输入单词 “copy” 。

Vim 会把我们离开插入模式之前的全部按键操作记录都记下来,所以刚才的过程 cwcopy<Esc> 会被当作一个修改,也就是说,现在的 . 命令会删除当前光标到单词结尾处的字符,并把它修改为“copy”。

接下来按下 n 键,光标会跳到下一个 “content” ,接着再按下 . 键时,会把光标下的单词换为“copy”。

连起来就可以 n. n. 的操作了

We'are waiting for copy before .... If you are copy with this, ... as soon as we
have the copy..

复制与粘贴
#

Vim 的剪切、复制、粘贴有别于其他编辑器。

命令 Others Vim
复制 copy yank
剪切 cut delete
粘贴 paste put

Vim 的 put 命令与粘贴命令完全相同。 Vim 的 yank 命令等同于复制操作。至于为什么用 yank 而不是 copy ,这就是历史遗留原因了。 当时的 c 命令被用于 修改(change)操作了,所以被迫换成了 yank 这个名字。 Vim 的 delete 也与标准的剪切操作一致。该命令会把指定文本复制到寄存器后再从文档中删掉。

用无名寄存器实现删除、复制与粘贴操作
#

通常情况下,复制、粘贴和操作指的是操纵系统的剪贴板。在 Vim 中,操作的是寄存器。

调换字符
#

手速太快有时候会习惯性的输错某个单词,常见的比如两个字母的顺序输错了。

 Practica lvim

上面把 “l” 和空格的顺序输入反了,现在我的光标在最后一个字母 “m” 上, 按下 F<space> 在本行文本中找到光标之前的空格,按下 x 把光标下的字符剪切下来放到无名寄存器。最后按下 p 命令将无名寄存器的内容粘贴到光标后面。

最后把两个命令组合到一起,即 xp ,可以 “调换光标后的两个字符”,现在我的光标在最后一个字母 “m” 上, 按下 F<space> 在前文中找到空格,按下 x 把光标下的字符剪切下来放到无名寄存器。最后按下 p 命令将无名寄存器的内容粘贴到光标后面。

 Practical vim

调换文本行
#

类似的,也可以方便的调换两行文本的顺序。这次,用 dd 命令剪切当前行,将内容放到无名寄存器中,再按下 p 会把内容粘贴到当前行的下一行。 把命令连接起来即 ddp ,可以用来“调换当前行和它的下一行”。

// before
我是第二行;
我是第一行;
我是第三行;
// after
我是第一行;
我是第二行;
我是第三行;

创建文本行的副本
#

类似调换文本行,创建文本行的副本只需要将剪切行的命令 dd 换成复制一行文本的命令 yy 即可,连起来是 yyp,可以用来“复制当前行并在下一行粘贴文本”。

// before
我是第一行;
我是第二行;
// after
我是第一行;
我是第一行;
我是第二行;

深入理解 Vim 寄存器
#

引用一个寄存器
#

Vim 的删除、复制和粘贴都会用到众多寄存器中的一个 。 可以通过给命令加 “{register} 前缀的方式指定要用的寄存器。若不指明,Vim 将使用无名寄存器。

  • 举例 如果想把当前单词复制到寄存器 a 中, 可以执行 “ayiw 。 把当前整行文本剪切到寄存器 b 中, 可以执行 “bdd

“ap 可以粘贴来及寄存器 a 的单词, “bp 可以粘贴来及寄存器 b 的一行文本,两者互不干扰。

无名寄存器("")
#

倘若我们没有指定使用寄存器, Vim 将缺省使用无名寄存器,它可以双引号表示。

  • 举例 例如 ““p 这个命令,他完全等同于 p 命令。

复制专用寄存器 (“0)
#

当使用 y{motion} 命令时,要复制的文本不仅会拷贝到无名寄存器中,同时也拷贝到了复制专用寄存器中。后者可以用数字 “0” 加以引用。

  • 举例

例如有以下代码

var myCat1 = new cat();
var myCat2 = new dog();

现在想要把 “dog” 换为 “cat”。若是之前不知道寄存器这个概念的话,场景会是这样:

  1. 光标到 “cat” 上面,按下 yiw 复制这个单词
  2. 把光标移动到 “dog” 上面,按下 diw删除这个单词
  3. 按下 p 粘贴
  4. 懵了:本来想粘贴 “cat” 的,结果粘贴的内容却是 “dog” ,第一步复制的 “cat” 不见了

发生这个问题原因是一直使用的是无名寄存器,当删除单词时,删除操作会把单词放到无名寄存器中,把之前复制的内容给“挤”走了。

现在有了复制专用寄存器就不虚了。在最后粘贴的时候按下 “0p 而不是 p 就完美的解决了这个问题。

var myCat1 = new cat();
var myCat2 = new cat();

有名寄存器(“a - “z)
#

Vim 提供了一组以 26 个英文字母命名的寄存器,这意味着我们可以复制、剪切或者粘贴多达 26 段文本。 上面改名字的问题使用有名寄存器也能很轻松地解决,这里就不再赘述了。

  • 用小写字母引用有名寄存器,会覆盖该寄存器的原有内容。
  • 用大写字母引用有名寄存器,会将新内容添加到原有内容之后。

黑洞寄存器 (”_)
#

想要删除一段文本而不想保留副本时,黑洞寄存器就很管用了。 使用 “_diw 删除一个单词时, 不会将之前无名寄存器的内容覆盖。

系统剪切板("+)与选择专用寄存器(”*)
#

到目前为止,讨论的寄存器都是 Vim 内部的,如果想从 Vim 复制内容到外部,则必须使用系统剪切板。

Vim 的加号寄存器与系统剪切板等效,可用 +号引用。 比如现在从别的程序中复制了一段文本,在 Vim 中,就可以通过 “+p 命令将其粘贴到 Vim 内部。 如果在 Vim 的复制、粘贴和剪切命令之前加上 “+ ,相应的文本会捕捉至系统剪切板。

在 Windows 和 Mac OS 中, “+ 寄存器 和 “* 寄存器 可以混用。

实践中常用的 vim 命令
#

vim 删除文本中所有的 "

.,$s/\"//g

vim 将文本中所有的回车换为逗号

.,$s/\n/,/g