0%

学习 vi 和 vim 编辑器(2):越过基础的藩篱

上一篇文章 已经对 vi 基础知识作了介绍,这一篇文章继续探索 vi,学习更多技巧,包括如何快速移动位置、搜索、打开文件时的选项、标记等等。

快速移动位置

通常,编辑文本所需要做的第一步就是将光标移动到需要编辑的地方,因此编辑文本的速度一定程度上取决于将光标移动到目的地所需要的按键数。接下来会介绍几种快速移动光标到目的地的方法。

根据屏幕来移动

vi 允许以屏幕为单位来快速移动光标,此时可以把文件看成一个具有文字的长长的卷轴,而屏幕则是一个窗口:

  • ^F:向前(往文本结尾方向)滚动一整屏
  • ^B:向后(往文本开头方向)滚动一整屏
  • ^D:向前滚动半屏
  • ^U:向后滚动半屏
  • ^E:向前滚动一行
  • ^Y :向后滚动一行

如果想在滚动屏幕时让光标维持在原来的文本行,可以使用 z 命令:

  • z+enter:滚动屏幕,将光标所在行置于屏幕顶端
  • z. :滚动屏幕,将光标所在行置于屏幕中央
  • z-: 滚动屏幕,将光标所在行置于屏幕底端

你会发现重复相同的 z 命令没有意义,因为第一次执行相应的命令后就已经达到目的了,再执行相同的命令没有效果。

可以通过如下命令,在当前屏幕视图范围内移动:

  • H:移动到屏幕顶端的行
  • M:移动到屏幕中央的行
  • L:移动到屏幕底端的行
  • nH:移动到屏幕顶端往下第 n 行
  • nL:移动到屏幕底端往上第 n 行

另外,当某些消息出现在屏幕上而影响工作时,可以通过滚动屏幕来消除这些消息,或者也可以通过 Ctrl + L 命令来重绘屏幕。

根据行移动

上一篇文章已经介绍了几个以行为单位进行移动的命令,这里再补充几个命令。

  • enter:移动到下一行第一个非空字符处
  • +:移动到下一行的第一个非空字符处
  • -:移动到上一行的第一个非空字符处

可以使用如下命令在当前行中移动:

  • ^:移动到当前行的第一个非空字符处
  • n|:移动到当前行的第 n 列

根据文本块来移动

vi 编辑器支持以文本块(单词,句子,段落或小节)为单位进行移动。之前已经介绍了以单词为单位进行移动,接下来再介绍其它的根据文本块来移动光标的命令:

  • (: 移动到当前句子的开头
  • ) :移动到下一个句子的开头
  • {: 移动到当前段落的开头
  • } :移动到下一段落的结尾
  • [[:移动到当前这一节的开头
  • ]]:移动到下一节的开头

vi 会寻找 ? . ! 等标点符号,当这些标点符号后面紧跟空格、tab 或空行时,vi 将其作为句子的结束。段落的定义则是下一个空白行前的文本,或者是出现在段落宏之前的文本。而小节的定义则是下一个节宏之前的文本。可以通过 :set 命令自定义这些被当成段或节分隔符的宏。

根据搜索模式来移动

在大文件中移动时,最快速的方法之一就是根据搜索模式的结果来进行移动。搜索命令是特殊字符 /,命令格式为 /patten。模式可以是完整的单词,或者一连串字符串。如果在搜索模式中加入了空格,这个空格也会被成单词的一部分,当然还可以使用更强大的模式匹配语法。

  • /patten:从光标位置开始处往前搜索
  • ?patten:从光标位置开始处往回搜索

vi 会从光标当前位置开始搜索,如果搜索到了,光标会定位在该搜索模式第一次出现的地方,否则在屏幕底端显示相应的提示信息。

搜索命令可以与文本修改命令结合使用,也就是说其也支持 (command)(TextObject) 的使用形式,搜索命令可以出现在 TextObject 中。

重复搜索

上一次的搜索模式会留在你的编辑会话中,因此可以不用输入原来的搜索模式,而直接重复上一次搜索:

  • n: 往同一个方向上重复搜索
  • N:往相反方向上重复搜索
  • /enter: 往前重复搜索
  • ?enter:往后重复搜索

需要注意,重复搜索时 vi 默认会自动绕回文件头或文件尾。可以通过设置 wrapscan 选项来控制搜索是否要绕回,输入命令 :set nowrapscan ,就可以取消搜索时绕过文件头或文件尾。

在当前行中搜索

可以用如下命令在当前行中搜索移动:

  • fx:搜索(同时将光标移动到)本行下一个出现 x 的位置,x 代表任何字符
  • Fx:搜索(同时将光标移动到)本行前一个出现 x 的位置
  • tx:搜索(同时将光标移动到)本行下一个出现 x 的位置的前一个字符
  • Tx:搜索(同时将光标移动到)本行前一个出现 x 的位置的后一个字符
  • ;:重复上一个搜索,方向相同
  • ,:重复上一个搜索,方向相反

这些命令可以加上数值参数,代表搜索 x 字符第 n 次出现的地方。

其它移动技巧

输入两个反引号可以回到上一次光标所在位置,如果你在这中间做了编辑操作,该命令将光标移回到上次编辑的位置。如果使用了搜索命令,该命令可以将光标移回到上一次搜索时的位置。 “ 命令作用类似,只不过它将光标移回到上次位置所在行的开头而不是真实的位置。

打开文件时的选项

上一篇文章讲过,通过 vi [filename] 即可使用 vi 编辑器来编辑文件,其实该命令还有很多好用的选项。

定位到特定位置

可以在命令行中告诉 vi,在打开文件后光标第一次移动的方式,例如根据行号或搜索结果移动:

  • vi +n file:在第 n 行打开文件
  • vi + file:在最后一行打开文件
  • vi +/pattern file :在第一个出现 pattern 的地方打开文件

介绍两种使用这几个命令的场景:

  • 当编译一个源文件出错时,编译器会把相关的行号信息显示出来。此时我们可以直接在打开文件时就定位到相应的行上
  • 在编辑文件时,如果正好编辑到一半而不得不暂时离开,可以用某个模式将当前位置标记起来,例如字符串 HERE。当我们回来时,只需要 vi +/HERE filename 即可

只读模式

vi 允许以只读模式打开一个文件,这样就不用担心不经意间修改文件了:

vi -R filename
view filename

如果在只读模式中想要修改文件并保存,需要在使用:w!,感叹号代表忽略只读模式。

恢复缓冲区

在编辑文件时,如果系统发生了错误,此时自上一次保存以来所做的文件修改都会消失,可以使用 -r 选项恢复系统死机时的编辑缓冲区。

  • vi -r 或 ex -r :获取系统保存下来的所有文件列表
  • vi -r filename: 恢复指定文件对应的编辑缓冲区
  • :pre:强制系统保存当前缓冲区

善加利用缓冲区

之前已经提过,对于最后一次删除或拖曳的内容(删除和拖曳操作共享相同的缓冲区)会被保存到临时缓冲区,使用放置命令 p 可以将这些文本放回到文件中。

同时,vi 编辑器会将最后九次删除操作保存到有编号的缓冲区中,可以恢复这些缓冲区中的任何一个。但是只有以行为单位的删除本文才会被保存到编号缓冲区中,对于删除一行中的一部分,或者单词的一部分等,都不会被保存到编号缓冲区中,此时只能在删除操作发生后立即用 p 命令进行恢复。

在这些编号缓冲区中,最后一次删除的内容保存在缓冲区1,倒数第二次删除的内容保存到缓冲区2,依此类推。如果要恢复某个编号缓冲区内容,首先输入 “(双引号),再指定缓冲区编号,最后使用放置命令即可。

同时,vi 允许将拖拽或删除的文本放到以字母为标号的命名缓冲区中。这些文本可以保存到26个缓冲区(a-z)中,并且可以在编辑会话的任何时候使用放置命令来恢复这些文本。如果某个命名缓冲区中已经存放了文本,若此时继续向该缓冲区中放置文本,则新的文本会覆盖该缓冲区中已经存在的内容。

要将文本保存到命名缓冲区中,需要在拖曳或删除命令之前加上双引号 “ 以及缓冲区的名字(a-z)。恢复时,只需要输入双引号 “,加上缓冲区的名字(a-z),以及放置命令p,即可恢复指定命名缓冲区的内容。

当使用大写字母指定缓冲区时,拖曳或删除的文本会附加到相应的缓冲区中。

标记

vi 允许在文本的某处做一个看不见的标记,然后通过相关的命令移动到指定标记。需要注意的是,标记只在当前编辑会话中有效,并不会保存在文件中。

  • mx:将当前位置标记为 x( x 可以是任何字符)
  • ‘x:将光标移动到标记 x 所在行的第一个字符
  • 反引号x:将光标移动到 x 标记所在字符处