2020-04-09
背景介绍
第一版 vi
是在 1976 由 Bill Joy 写成的,当时他是加州大学伯克利分校的学生,后来他共同创建了 Sun 微系统公司。vi
这个名字来源于单词“visual
”,因为它打算在带有可移动光标的视频终端上编辑文本。在发明可视化编辑器之前,有一次只能操作一行文本的行编辑器。为了编辑,我们需要告诉行编辑器到一个特殊行并且说明做什么修改,比方说添加或删除文本。视频终端(而不是基于打印机的终端,像电传打印机)的出现,使可视化编辑成为可能。vi
实际上整合了一个强大的行编辑器——ex
, 所以我们在使用 vi
时能运行行编辑命令。
大多数 Linux 发行版不包含真正的 vi
;而是自带一款高级替代版本,叫做 vim
(它是“vi improved”的简写)由 Bram Moolenaar 开发的。vim
相对于传统的 Unix vi 来说,取得了实质性进步。通常,vim
在 Linux 系统中是“vi
”的符号链接(或别名)。
启动和退出 vi
要想启动 vi,只要简单地输入以下命令:
[me@linuxbox ~]$ vi
要退出 vi,输入下面的命令(注意冒号是命令的一部分):
:q
shell 提示符应该重新出现。如果由于某种原因,vi 不能退出(通常因为我们对文件做了修改,却没有保存文件)。通过给命令加上叹号,我们可以告诉 vi 我们真要退出 vi。(注意感叹号是命令的一部分)
:q!
小贴示:如果你在 vi 中“迷失”了,试着按下 Esc
键两次来回到普通模式。
编辑模式
再次启动 vi,这次传递给 vi 一个不存在的文件名。这也是用 vi 创建新文件的方法。
插入模式
为了在文件中添加文本,我们需要先进入插入模式。按下 “i
” 键进入插入模式。之后,我们应当在屏幕底部看到如下的信息,如果 vi 运行在高级模式下(vi 在兼容模式下不会显示这行信息):
-- INSERT --
保存我们的工作
为了保存我们对文件所做的修改,我们必须在命令模式下输入一个 ex
命令。通过按下 “:
”键,这很容易完成。按下冒号键之后,一个冒号字符应该出现在屏幕的底部。
为了写入我们修改的文件,我们在冒号之后输入 “w
” 字符,然后按下回车键:
:w
文件将会写入到硬盘,而且我们会在屏幕底部看到一行确认信息,就像这样:
"foo.txt" [New] 1L, 46C written
小贴示:如果你阅读 vim 的文档,你会发现命令模式被(令人困惑地)叫做普通模式,
ex
命令叫做命令模式。当心。
移动光标
为什么 h,j,k,和 l 按键被用来移动光标呢?因为在开发 vi 之初,并不是所有的视频终端都有箭头按键,熟练的打字员可以使用组合键来移动光标,他们的手指从不需要移开键盘。
vi 中的许多命令都可以在前面加上一个数字,比方说上面提到的 “G” 命令。在命令之前加上一个数字,我们就可以指定命令执行的次数。例如,命令 “5j” 将光标下移 5 行。
基本编辑
vi 也提供了撤销功能,但有些限制。如果我们按下“u
”按键,当在命令模式下,vi 将会撤销你所做的最后一次修改。
追加文本
vi 提供了追加文本的命令,明智地命名为 “a
”。如果我们把光标移动到
行尾,输入”a
”, 光标就会越过行尾,同时 vi 会进入插入模式。
记得按 Esc
键来退出插入模式。
因为我们几乎总是想要在行尾添加文本,所以 vi 提供了一个快捷键。光标将移动到行尾,同时 vi 进入输入模式。它是 “A
” 命令。试着用一下它,向文件添加更多行。
打开一行
我们插入文本的另一种方式是“打开(open)”一行。这会在两行之间插入一个空白行,并且进入到插入模式。这种方式有两个变体:
删除文本
正如我们所愿,vi 提供了各种删除文本到的方法,而且只需一或两个按键。首先,x
按键会删除光标位置的一个字符。可以在 x
命令之前带上一个数字,来指明要删除的字符个数。d
按键更通用一些。跟 x
命令一样,d
命令之前可以带上一个数字,来指定要执行的删除次数。另外,d
命令之后总是带上一个移动命令,用来控制删除的范围。这里有些实例:
注意:真正的 vi 只是支持单层面的 undo 命令。vim 则支持多个层面的。
剪切,复制和粘贴文本
这个 d
命令不仅删除文本,它还“剪切”文本。每次我们使用 d
命令,删除的部分被复制到一个粘贴缓冲区中(看作剪切板)。过后我们执行小 p
命令把剪切板中的文本粘贴到光标位置之后,或者是大 P
命令把文本粘贴到光标之前。
y
命令用来“拉”(复制)文本,和 d
命令剪切文本的方式差不多。这里有些把 y
命令和各种移动命令结合起来使用的实例:
连接行
vi 对于行的概念相当严格。通常,用户不可能通过删除“行尾结束符”(end-of-line character)来连接当前行和它下面的一行。由于这个原因,vi 提供了一个特定的命令,大写的 J
(不要与小写的 j
混淆了,j
是用来移动光标的)用于连接行与行。
查找一行
f
命令能搜索一特定行,并将光标移动到下一个匹配的字符上。例如,命令 fa
会把光标定位到同一行中下一个出现的 “a
” 字符上。在进行了一次行内搜索后,输入分号能重复这次搜索。
查找整个文件
移动光标到下一个出现的单词或短语上,使用 /
命令。这个命令和我们之前在 less 程序中学到的一样。当你输入/
命令后,一个 “/
” 字符会出现在屏幕底部。接下来,输入要查找的单词或短语,按下回车。光标就会移动到下一个包含所查找字符串的位置。通过 n
命令来重复先前的查找(继续向后查找)。
全局查找和替代
vi 使用 ex 命令来执行查找和替代操作(vi 中叫做“替换”)。
将整个文件中的单词“Line”更改为“line”,输入以下命令:
:%s/Line/line/g
我们把这个命令分解为几个单独的部分,看一下每部分的含义:
我们也可以指定一个需要用户确认的替换命令。通过添加一个 “c
” 字符到这个命令的末尾,来完成这个替换命令。例如:
:%s/line/Line/gc
这个命令会把我们的文件恢复先前的模样;然而,在执行每个替换命令之前,vi 会停下来,通过下面的信息,来要求我们确认这个替换:
replace with Line (y/n/a/q/l/^E/^Y)?
括号中的每个字符都是一个可能的选择,如下所示:
如果你输入 y
,则执行这个替换,输入 n
则会导致 vi 跳过这个实例,而移到下一个匹配项上。
编辑多个文件
通过 vi,我们可以打开多个文件来编辑,只要在命令行中指定要编辑的文件名。
vi file1 file2 file3...
文件之间切换
从这个文件切换下一个文件,使用这个 ex 命令:
:n
回到先前的文件使用:
:N
当我们从一个文件移到另一个文件时,如果当前文件没有保存修改,vi 会阻止我们切换文件,这是 vi 强制执行的政策。在命令之后添加感叹号,可以强迫 vi 放弃修改而转换文件。
我们可以查看正在编辑的文件列表,使用:buffers
命令。运行这个命
令后,屏幕顶部就会显示出一个文件列表。
要切换到另一个缓冲区(文件),输入:buffer
, 紧跟着你想要编辑的缓冲器编号。比如,要从包含文件 foo.txt 的 1 号缓冲区切换到包含文件 ls-output.txt 的 2 号缓冲区,我们会这样输入:
:buffer 2
我们的屏幕现在会显示第二个文件。
打开另一个文件并编辑
在我们的当前的编辑会话里也能添加别的文件。ex 命令:e
(编辑 (edit) 的简写) 紧跟要打开的文件名将会打开另外一个文件。让我们结束当前的会话回到命令行。
注意:当文件由:e
命令加载,你将无法用:n
或:N
命令来切换文件。这时要使用:buffer
命令加缓冲区号码,来切换文件。
跨文件复制黏贴
当我们编辑多个文件时,经常地要复制文件的一部分到另一个正在编辑的文件。使用之前我们学到的拉(yank)和粘贴命令,这很容易完成。
说明如下。以打开的两个文件为例,首先转换到缓冲区 1(foo.txt),输入:
:buffer 1
下一步,把光标移到第一行,并且输入 yy
来复制这一行。
转换到第二个缓冲区,输入:
:buffer 2
移动光标到第一行,输入 p 命令把我们从前面文件中复制的一行粘贴到这个文件中。
插入整个文件到另一个文件
:r
命令(是 “read” 的简称)把指定的文件插入到光标位置之前。
保存工作
像 vi 中的其它操作一样,有几种不同的方法来保存我们所修改的文件。我们已经研究了:w
这个 ex 命令,但还有几种方法,可能我们也觉得有帮助。
在命令模式下,输入 ZZ
就会保存并退出当前文件。同样地,ex 命令:wq
把:w
和:q
命令结合到一起,来完成保存和退出任务。
这个:w
命令也可以指定可选的文件名。这个的作用就如 “Save As…”。例如,如果我们正在编辑 foo.txt 文件,想要保存一个副本,叫做 foo1.txt,那么我们可以执行以下命令:
:w foo1.txt
注意:当上面的命令以一个新名字保存文件时,它并没有更改你正在编辑的文件的名字。如果你继续编辑,你还是在编辑文件 foo.txt,而不是 foo1.txt。