Vi 入门
现在大多数开始使用 Linux 或 UNIX 的人已经知道如何使用图形化的 WYSIWYG(所见即所得)编辑器,大量使用鼠标、图标和下拉菜单。当他们第一次接触传统的 UNIX/Linux 编辑器 vi 时,它可能看起来笨拙且功能不强大,但事实恰恰相反。
与图形编辑器一样,您可以选择一段文本并执行命令进行更改,通过指示光标应在的位置来移动光标,并通过在键盘上键入来插入文本。不同之处在于 vi 不使用鼠标;您使用键盘来指定更改或移动光标。为了使整个键盘可用于命令,vi 具有单独的命令模式和插入模式。
模式起初可能会令人困惑。对于大多数编辑器,您键入的任何内容都会进入文档,并且编辑是通过鼠标或键盘快捷键完成的。对于 vi,命令模式使用整个键盘来指定编辑命令。只有当您发出插入命令时,键盘才会向文档添加文本。
大多数新的 vi 用户只学习几个基本命令:箭头键,i 用于插入,x 用于删除字符,dd 用于删除行,:wq 用于保存并退出,以及其他一些。他们很快就会厌倦一遍又一遍地按相同的键,但又害怕学习大量的命令。
我们不只是提供一个需要记忆的列表,而是探索它们背后的结构,这使得命令更容易记住,并使您能够快速成为 vi 高级用户。命令有几个基本类别,包括插入文本、移动光标、块编辑命令、冒号 (ex) 命令、选项和杂项命令。
在 vi 中要学习的第一个命令是 i。键入 i 将编辑器置于插入模式,在该模式下,您键入的所有内容都会插入到文档中,直到您按下 Esc 键。但 i 不是插入文本的唯一方法。
要在光标后添加文本,例如在行尾,请使用 a。或者跳转到行尾并使用 A 追加文本。同样,I 在行首插入。对于这些和其他插入命令,始终按 Esc 返回到命令模式。
使用 o 在当前行之后打开一个新行并在那里插入文本,或使用 O 在当前行之前打开。
用 s 替换当前字符,或使用 R 替换多个字符,类似于图形编辑器中的覆盖模式。
几乎所有的 vi 命令都允许使用数字前缀,数字前缀通常会重复该命令指定的次数。例如,键入3iHooray然后按 Enter 和 Esc。它会在您的缓冲区中插入三行 “Hooray”。s 命令有所不同;在这里,数字表示要替换多少个字符:5s 将五个字符替换为您键入的任何内容。
一些控制键在插入模式下具有特殊含义。您可以使用箭头键来移动,但不要忘记您仍处于插入模式。此外,Ctrl-T 和 Ctrl-D 在行首时可用于缩进。Ctrl-T 移动到下一个缩进级别,Ctrl-D 向后移动。将这些与 autoindent 和 shiftwidth 选项(在下面的“选项”部分中描述)一起使用可获得最佳效果。
图形编辑器主要通过单击鼠标来移动。一些 vi 克隆提供了鼠标支持,但 vi 及其所有克隆都共享移动命令,这些命令可以使您快速移动。最简单的是箭头键或等效字母:h(左)、j(下)、k(上)和 l(右)。但是,如果这些是您使用的全部,那么您就错过了 vi 的全部功能。
您可以通过按住向右或向左箭头键(或 l 或 h)在一行中向前和向后移动,但还有更简单的方法。使用 ^ 转到行首,或使用 $ 转到行尾。要一次跳一个单词,请使用 w 或 W 向前移动,或使用 b 或 B 向后移动。您还可以使用 e 或 E 跳到当前单词的末尾。对于小写 w、b 和 e,单词是字母数字字符的序列;大写版本使用空格分隔单词。
在当前行中移动的另一种方法是跳转到特定字符。例如,要将光标移动到行中的下一个 s,请键入 fs。对于上一个,请使用 F:Fs。或者使用 ts 转到 s 的正前方,使用 Ts 向另一个方向移动。更改 s 以搜索任何字符。键入 ,(逗号)以重复任何这些搜索。
要将光标移动到屏幕的顶部、中间或底部,请使用 H、M 或 L(大写)。对于 H 或 L,数字前缀表示您要从屏幕顶部或底部移动多少行;它对 M 没有影响。
要按句子来回跳转,请键入 ( 或 );对于段落,请使用 { 和 }。如果您正在编辑带有大量括号的源代码,请尝试 % 命令:将光标放在以下任何字符上:(、)、[、]、{ 或 },然后按 %;您将被带到匹配的括号。
通常,移动的最佳方式是使用 / 命令进行搜索。例如,键入/hello然后按 Enter 跳转到文档中的下一个 “hello”。您可以输入任何正则表达式来代替 “hello”。n 命令重复搜索;N 向另一个方向移动。或者使用 ? 在文件中向后搜索。搜索区分大小写;我将在本文后面讨论 ignorecase 选项。
对于大多数移动命令,可以使用数字前缀来重复。例如,5w 将您向前移动五个单词,2n 不会跳转到下一个搜索匹配项,而是跳转到其后的一个,而 5fs 跳转到光标右侧的第五个 s。
在图形编辑器中,要更改文本块,请单击并拖动鼠标以突出显示文本,然后单击图标或菜单选项或键入键盘快捷键。虽然 vi 不使用鼠标,但该过程惊人地相似。
正如我们刚刚看到的,vi 具有丰富的移动命令集。这些命令中的任何一个都可以作为块编辑命令的参数(例如,dw 删除一个单词)。在 vi 中,您无需先用鼠标突出显示并选择操作,而是先键入块编辑命令 (d),然后 再 键入移动命令 (w) 以指定文本块。作为快捷方式,您可以键入两次块编辑命令以仅影响当前行,例如,dd 删除当前行。
正如我们所见,d 用于删除。每当您删除文本时,都会记住该文本,很像图形编辑器中的剪切命令。要粘贴文本(在 vi 术语中为 “put”),请键入 p 将其放在光标位置之后(或大写 P 放在之前)。
这解决了剪切和粘贴的问题,但复制呢?在 vi 中,它被称为 “yank” 并使用 y 命令完成。这些命令与 d 命令完全相同,只是它们不删除任何内容:yy 抽出当前行,yw 抽出一个单词,依此类推。
要替换一大段文本,您可以先删除它,然后使用 i 插入替换项,或者改用 c(更改),您将被置于插入模式以键入替换文本;完成后按 Esc。与移动命令(例如 cw)一起使用,或使用 cc 更改整行。
程序员会喜欢 > 和 < 命令。这些命令将一段文本向右或向左移动。要移动代码块,请将光标放在块的开头或结尾的 { 或 } 字符上,然后键入 >% 将其向右移动。任何其他移动命令都可以代替 % 使用,或者使用 >> 移动一行。使用 < 向左移动。另请参阅 Ctrl-T 和 Ctrl-D(在插入模式下)以及下面的 shiftwidth 选项。
最后,使用 ! 通过外部程序过滤文本。键入要运行的程序,选定的文件部分将作为标准输入传递;程序的输出将插入到文档中的原位置。例如,!! 过滤当前行;!} 过滤一个段落。与此特别有用的一个命令是 UNIX/Linux 过滤器 fmt,它可以重新格式化段落。要在不修改文件的情况下运行外部程序,请参阅 “冒号 (ex) 命令” 部分中的 :! 命令。
给出的任何数字前缀都将传递给命令的移动部分,无论它是首先给出还是在编辑命令和移动命令之间给出。例如,3dw 或 d3w 都删除三个单词;3yy 或 y3y 都抽出(复制)三行。
Vi 从其前身 ex 继承了一类命令,可以通过有时称为冒号模式的方式访问。常见的示例是 :wq(写入并退出)和 :s/X/Y/(用 Y 替换 X)。键入 :,后跟一个 ex 命令,然后按 Enter。命令完成后,vi 返回到命令模式。
:w 和 :q 命令有几种变体。要保存文件并继续编辑,请使用 :w。您可以使用 :q 退出 vi,但前提是您的工作已保存;要无论如何都退出,请使用 :q!(危险)。如果 :q 给出错误,请尝试 :w! 以覆盖只读模式。许多人使用 :wq! 写入并退出。在 vim 或 nvi 中,这就像键入 :w!,然后在保存时没有错误的情况下键入 :q。但是其他一些版本的 vi 将其视为 :w 和 :q!,这意味着如果保存文件时出现任何错误,工作将会丢失。因此,最好养成使用 :wq 的习惯。
替换命令非常强大。在其最简单的形式中,:s/X/Y/ 将当前行中 X 的一个实例替换为 Y。要替换一行中的所有实例,请在末尾添加 g(全局),例如 :s/foo/bar/g。在末尾添加 c 以确认每次更改,例如 :s/foo/bar/gc。要更改一系列行,请在前面放置两个用逗号分隔的行号,例如 :10,20s/foo/bar/g 将第 10 行到第 20 行中的所有 “foo” 实例替换为 “bar”。使用 1 表示文件的第一行,使用 $ 表示最后一行;要在所有行上替换,请使用 :1,$s/foo/bar/g(而不是 1,$,您可以使用 %,如 :%s/foo/bar/g)。
另一个有用的命令是 :g/X/。它允许您为与模式 X 匹配的所有行运行任何 ex 命令。例如,要将包含 “hello” 的所有行打印到屏幕上,请使用 :g/hello/p(:p 是用于将行打印到屏幕的 ex 命令)。您甚至可以将其与 :s/// 命令结合使用。要将包含 “hello” 的所有行中的 “foo” 更改为 “bar”,请使用 :g/hello/s/foo/bar/g。
在 :s/X/Y/ 和 :g/X/ 中,表达式 X 是正则表达式,而不仅仅是静态字符串。设置 nomagic 选项可以禁用此功能(见下文)。要了解正则表达式,我推荐 Jeoffrey Friedl 的 精通正则表达式 一书(O'Reilly & Associates,第二版,2002 年)。
使用 :! 运行外部程序。:!ls 打印当前目录列表。为了方便起见,命令中的百分号 (%) 将替换为您当前正在编辑的文件名,因此使用 :!chmod +x % 使文件可执行。键入 :!! 重复上一个 :! 命令。与命令模式下的 ! 命令不同,这不会修改文本;程序的输出(如果有)只是简单地显示出来。
在 vi 中,您可以使用 ex :set 命令设置选项以更改编辑器的行为。例如,搜索命令通常区分大小写;要更改此设置,请使用 :set ignorecase 或 :set ic 选项。大多数选项都有两个字母的缩写版本。
选项有两种类型:布尔值(真/假)选项和取值的选项。要关闭布尔值选项,请在前面添加 “no”;例如,:set noignorecase 或 :set noic 关闭 ignorecase 选项。
对于取值的选项,请使用等号后跟要设置的值。例如,shift 命令(>、<、^T 和 ^D)的默认间距为八个空格(一个制表符),但大多数程序员更喜欢两到四个空格。使用 :set shiftwidth=4(或 :set sw=4)使所有缩进命令使用四个空格的缩进。
以下是一些其他有用的选项
wrapmargin=N 启用自动换行;指定在行尾之前多少个字符处换行,例如 :set wm=8。
autoindent(布尔值)将您键入的每一行缩进与上一行相同的量,例如 :set ai。
magic(布尔值,默认值为 true,无缩写)控制搜索命令中的正则表达式行为,例如 :set nomagic。
要一次设置多个选项,请将它们组合成一个 set 命令,如下所示::set noic wm=8 sw=4 nomagic ai。
要为以后的编辑会话保存选项,请将它们放在您的 .exrc 文件中。当您运行 vi 时,它会运行在该文件中找到的任何 ex(冒号模式)命令。省略 : 字符,只需输入 set 命令即可。
图形编辑器的滚动条会告诉您您在哪里,您可以单击它来查看文件的其他部分。由于 vi 没有滚动条,因此它使用等效的键盘命令。
Ctrl-G 显示文件状态,包括当前行号。使用 XG 命令转到文件的特定行。G 本身跳转到文件末尾,或者使用 :X 作为 XG 的替代方法。
Ctrl-F 向前滚动屏幕一页,Ctrl-B 向后滚动一页。要以半页增量移动,请使用 Ctrl-D(向下)或 Ctrl-U(向上)。
一些其他杂项命令
x 命令删除当前字符(大写 X 向左删除)。数字前缀删除多个字符。使用此命令删除的文本与 d 命令一样被剪切。
~ 将当前字母从大写更改为小写,反之亦然。
使用 u 命令撤消错误。Vim 有多个级别的撤消。重复 u 命令会依次撤消每个步骤;Ctrl-R 键将它们放回原处(重做)。其他版本的 vi 只有一个级别的撤消;再次键入 u 只会撤消撤消,从而恢复更改。
大写 U 撤消到目前为止对当前行所做的所有更改;但是,一旦您离开该行,它就不再起作用。
键入 .(句点)以重复上次编辑命令。
要重复上次 :s/// 命令(但仅修改当前行),请键入 &。
Vi 的历史
vi 编辑器(名称是 “visual” 的缩写)最初由 Bill Joy 于 1976 年在加州大学伯克利分校编写。自那时以来,它一直包含在 UNIX 的 BSD(伯克利标准发行版)版本中,并且包括 Linux 在内的其他 UNIX 版本多年来也采用了它。
vi 编辑器是 ex 的后代,而 ex 又基于 ed。这些较旧的编辑器设计用于电传打字机,并且一次只能显示一行文本;vi 是第一个 UNIX 全屏文本编辑器。
由于版权原因(直到几个月前),原始 vi 的源代码一直不可用,但已经编写了许多克隆。大多数 Linux 发行版中包含的是 vim(vi improved)。当前的 BSD 标准编辑器是 nvi(new vi)。其他编辑器包括 elvis、vile 和 stevie。这些 vi 编辑器包括基本的 vi 功能,以及它们自己的附加功能。
资源
Vi 编辑器及其克隆:www.math.fu-berlin.de/~guckes/vi/index.php3 Vi 爱好者主页:www.thomer.com/vi/vi.html
William R. Ward (wrw@bayview.com) 自 1987 年以来一直在使用 vi。他是一位教师、作家和程序员,与妻子 Holly 住在加利福尼亚州山景城。他们的公司 Bay View Consulting Services (www.bayview.com) 提供 Perl、Linux/UNIX 和其他相关主题的培训课程。