0%

学习 vi 和 vim 编辑器(3):ex 编辑器概述

vi 编辑器使用的底层编辑器就是 ex 行编辑器,可以认为 vi 编辑器是 ex 行编辑器的可视化模式。ex 可以给你机动性更高,能力更强的编辑命令。ex 以行为导向,在对文件做大规模的改变时就成了优点。

打开文件

ex filename 命令使用 ex 行编辑器打开文件,它列出来了文件的总行数及命令提示符 :。此时无法看到文件的任何一行,除非下达显示一行或多行的ex命令。

ex 命令由行地址以及相应的操作命令构成。最基本的操作命令就是 p,用于打印行到屏幕,所以在命令提示符中输入 1p 表示打印第一行。此时甚至可以省略 p,单纯的输入行号等价于显示该行。可以在两个数值间用逗号分隔来指定一个行范围,例如 1,3 代表第 1 至第 3 行。没有指定行地址的命令只会对当前行起作用。

输入 :vi 命令可以从 ex 编辑器进入 vi 编辑器,也可以在 vi 编辑器中输入 Q 进入 ex 编辑器。想在 vi 编辑器中使用 ex 编辑命令,必须输入特定字符 :。

在 : 后面输入行号,就可以直接跳转到该行。例如 :6 等效于 vi 编辑器中的 6G 命令,都是将光标移动到第 6 行。

ex 操作命令

许多常见的 ex 操作命令在 vi 中都有相应的更简单的命令。但是当某个操作需要改变多行时,ex 命令可能更有用。常见的ex命令如下:

全名 缩写 功能
delete d 删除行
move m 移动行
copy co 复制行

另外, t 命令也可以实现复制行的功能。

行地址

每一个 ex 编辑命令都需要指定相应的行地址。指定行地址有如下几种方法:

  • 明确的指定行号
  • 用符号来指定相对于当前位置的行地址
  • 使用搜索模式作为行地址

指定行号

通过行号可以明确地指定某一行或某段行范围。明确地指定行号也称为绝对行地址。

例如

  • :3,18d:删除 3 到 18 行
  • :160,224m23:将第 160 行到第 244行 的内容移动到第 23 行之后
  • :23,29co100:将第 23 行到第 29行 的内容复制到第 100 行之后

数字 0 表示文件开头,也就是第一行文本之前。

通过 :set nu:set number 来显示行号,通过 :set nonu 或者 :set nonumber 来关闭行号的显示。另外,可以通过 # 来临时显示某些行的行号,例如 :1,10# 显示第 1 行到第 10 行的行号。

另外通过如下命令也可以得当行号的信息:

  • :=:列出文件的总行数
  • :.=:列出当前行的行号
  • :/pattern/=:列出 pattern 第一次出现时的行号

行寻址符号

可以使用符号表示行地址,这些行寻址符号可以与绝对行地址混合使用。

  • .:表示当前行,
  • $:表示文件的最后一行;
  • %:表示文件的每一行,等同于1,$的组合

以下是一些使用例子:

  • :.,$d:删除当前行到文件结尾间的文本
  • :20,.m$:将第 20 行到当前行的文件内容移动到文件结尾
  • :%d:删除文件的所有行
  • :%t$:将所有的行复制到文件的结尾(做连续的复制)

除了指定绝对行地址以外,还可以指定相对于当前这一行的地址。+ 与 - 代表加上或减去后面的数值,例如

  • :.,+20d :删除当前这一行到该行之后 20 行的文件内容
  • :226,$m.-2 :将第 226 行到文件结尾的文件内容移动到当前行的两行之前
  • :.,+20# :显示当前行及其之后 20 行的行号

其实使用 + 或 - 时不需要输入点号 .,因为默认就是将当前行作为开始的位置。

搜索模式

通过搜索模式也可以指定行地址。 例如:

  • :/pattern/d:删除下一个包含pattern的行
  • :/pattern/+d:删除下一个包含pattern的行的下一行
  • :/pattern1/,/pattern2/d:删除如下行范围,从第一个包含 pattern1 的行开始,截止到第一个包含 pattern2 的行

这些模式的前后都需要使用斜线作为分界线。

重新定义当前这一行的位置

当用分号代替逗号时,第一个行地址将会作为光标的当前地址,即使此时光标不在该行上。例如

  • :100;+5p 即可显示第 100 行及其之后 5 行的内容。

全局搜索

ex 中有一个全局命令 g,可以搜索模式并显示所有包含这个模式的行。而 :g! 的功能则正好与 :g 相反,搜索所有不包含指定模式的行。

  • :g/pattern:寻找并移动到文件最后一次出现 pattern 的地方
  • :g/pattern/p:寻找并显示文件中所有包含 pattern 的行
  • :g!/pattern/nu:寻找并显示文件中所有不包含 pattern 的行,同时显示所有找到行的行号
  • :60,124g/pattern/p:寻找并显示第 60 行与第 124 行之间所有包含 pattern 的行

合并ex命令

想输入新的ex命令,并不是每次都需要输入冒号。可以使用竖线 | 分隔命令,从而在同一个 ex 提示符号下合并多个命令。

保存和离开文件

:w 将缓冲区的内容写入到文件中,但不离开编辑器。编辑文件时应该经常使用 :w。

可以使用 :w new_file_name 的方式将当前编辑缓冲区的内容保存为新的文件。另外,结合使用 ex 的行寻址命令和写入命令,可以将文件中的某一部分进行保存。例如命令 :20,$w new_file_name,将当前文件的第 20 行到文件的结尾保存为新的文件,文件名为 new_file_name。

通过 Linux 的重定向操作符(>>)和写入命令(w),可以将缓冲区的一部分或全部内容追加到某个文件中。例如命令 :340,$w >> filename 会将当前文件的第 340 行到文件结尾的内容附加到文件 filename 中。

:read file_name 命令可以将某个已存在的文件复制到当前正在编辑的文件中,可以简写为 :r file_name。该命令会将文件 file_name 的内容插入到当前光标所在位置的下一行。可以在read 或 r 命令之前输入行号来指定插入的位置。

其他命令包括:

  • :q:离开编辑器
  • :wq:写入文件的同时离开编辑器。这是无条件写入,即使文件没有被修改
  • :x:写入文件同时离开编辑器。只有文件被修改过时才会写入

编辑多个文件

ex命令可以让我们在多个文件之间切换。vi 编辑器可以同时打开多个文件,例如 vi file1 file2 file 将同时打开 3 个文件。vi 默认将全屏显示第一个文件,可以使用 :n 在文件之间切换。

使用参数列表

除了使用 :n命令来切换到下一个文件,:args(简写为 :ar )可以列出命令行中的文件列表。当前正在编辑的文件名会用方括号括起,如下图所示:

:rewind(:rew) 命令会将当前文件复位为文件名列表中的第一个。vim 中提供了 :last 命令,用于将当前文件切换为文件名列表中的最后一个。

调用新文件

除了在编辑会话开始时打开多个文件,还可以在任何时候通过 :e file_name 命令来打开新的文件。但是在打开新文件之前,必须使用 :w 命令将当前文件进行保存(如果当前文件发生了修改)。

vi 会同时记住两个文件名,即当前文件名和候补文件名。当前文件名可以用 % 表示,候补文件名用 # 表示。

在当前文件尚未保存之前,vi 不会让你用 :e 或:n 命令来切换文件,除非在这些命令之后加上感叹后,从而强行忽略 vi 的限制。如果单纯的使用 :e! 命令可以放弃当前文件的编辑结果,直接回到文件上一次保存时的状态。

在文件之间做编辑

之前讲过命名缓冲区的概念,通过命名缓冲区可以更为简单的把文本从一个文件移动到另外一个文件。使用 :e 命令进行文件切换时,并不会清除命名缓冲区中的内容。因此可以将需要移动的文本保存到某个命名缓冲区中,在使用 :e 命令进行文件切换后,再把相应的命名缓冲区的内容放置到新文件中,就完成了文件之间的文本移动。

实现文本在文件之间移动的另一种方法是通过ex命令 :ya(拖动)与 :pu(放置)。通过这两个命令,再结合行寻址功能和命名缓冲区,也能够实现文件之间的文本移动。