学习 vi 编辑器/详细信息
学习 vi 编辑器: 熟悉 — 基本任务 — 使工作更轻松 — 高级任务 — 详细信息 — Vi 克隆 (Vim – 基本导航 – 模式 – 技巧和窍门 – 程序员需要了解的有用内容 – 增强 Vim – Vim 在 Windows 上 – VimL 脚本语言, Vile, BB vi) — vi 参考 |
本节描述了 vi 程序本身的一些细节(例如命令行功能)以及其他面向有抱负的 vi 高级用户的 vi 高级功能。
当然,不同的 vi 克隆有不同的启动程序(调用)方法。然而,通常情况下,vi 的命令行版本共享一组通用的基本命令行选项。以下这些命令行选项和标志通常可用。此外,vi 可以使用不同的名称启动。根据启动 vi 所使用的名称,它可能在行为上略有不同,或者加载不同的 vi 克隆。
常见的命令行选项和标志是
- -
或者
- -s
- 抑制。所有交互式用户反馈都将被抑制(不会写入终端)。这允许将编辑命令通过管道传输到编辑器,并将其用作一种流编辑器。在 Unix 上可能存在更好的流编辑器工具,例如 sed(1)、awk(1) 或 Perl(n)。
- 注意,"-" 是 Unix 中用来表示标准输入的常见符号。vi 作者选择它作为-s的替代方案,以便在通过管道传输命令时提供熟悉的外观。它并不真正意味着“从标准输入读取”,因为 vi 本来就那样做。
- -C
- cryptography(加密)。vi 会提示用户输入密钥(一种密码),并使用此密钥在写入之前对文件进行加密。它还会使用此密钥对使用 vi 打开的任何文件进行解密。此功能不受许多克隆支持,并且加密算法非常弱(它基于 256 个元素的单转子算法)。该算法很容易破解。它与 Unix crypt(1) 命令兼容。另请参见-x.
- -l
- (小写字母 L) 更改一些默认设置,使其更适合编辑 LISP 源代码。
- -L
- (大写字母 L) 列出在崩溃期间已保存的所有文件。请参见-r,也是。
- -r filename
- 在崩溃后恢复文件 filename。使用-L获取可以恢复的文件列表。
- -R
- 只读。文件只能查看,不能写入。
- -S
- 标签 未排序。当使用 tag 文件时,此标志告诉 vi tag 文件未排序,因此 vi 将使用较慢的算法查找标签。请参见-t,也是。
- -t tag
- 编辑(打开)包含给定 tag 的文件。当然,这需要一个名为 tags 的标签文件可用。
- -v
- 以可视模式启动。仅在编辑器以 ex 而不是 vi 的名称启动时才有用。
- -V
- 详细。通过标准输入读取的命令将回显到标准错误。这在编辑器用作流编辑器时进行调试时非常有用。
- -wnumber
- 窗口大小。将编辑器的行数设置为 number。vi 的行为就好像终端只有 number 行。这在过去使用缓慢的终端或调制解调器线路连接时用来加速操作。
- -x
- 加密。类似于-C。不同之处在于 vi 试图猜测要打开的文件是否需要解密。另一方面,-C在打开文件时始终运行解密操作。
- +command
或者
- -c command
- 在允许用户输入自己的命令之前执行命令 command。最常见的用法是使用它将编辑器定位在文件中的某个特定行。例如
vi +10 list.txt
- 将打开文件list.txt并将光标定位在第 10 行。另一种常见用法是指定一个模式
vi +/END script.awk
- 这将打开文件script.awk并将光标定位在模式 'END' 的首次出现位置。
如前所述,vi 可以使用不同的名称启动(并非所有名称都可用,具体取决于特定的克隆)
- vi
- 启动 vi 的常用方法。
- view
- vi 以只读模式启动。
- vedit
- 更改了一些设置以更适合初学者:magic 被清除,showmode 和 novice 被设置,并且 report 被设置为 1。
- ex -v
- 与直接输入vi
到目前为止,本教程只讨论了命令,以及命令如何与词语计数等内容结合使用。例如d2w已被解释为运算符delete 应用于两个词语。注意2w部分。您已经了解到这部分指定了运算符应该应用于哪些文本。事实上,2w部分指定了运算符应该应用于哪些文本对象(词语、行、字符等)。您已经看到相同的对象说明符可以与所有类型的运算符一起使用 - 只要组合有意义。
实际上,vi 命令遵循一个通用模式。命令由运算符和对象组成
[[count] operator] [[number] object]
这意味着操作符应该在数量个对象上执行次数次。几乎所有部分都是可选的。另外,有些操作符根本不接受对象。这种操作符/操作语法是vi的核心。这就是人们要么喜欢vi,要么讨厌vi的原因。人们喜欢它,因为它是一个如此简单的模式。一旦一个人了解了几个操作符(不超过十个),以及几个对象,就可以在vi中非常高效地工作。那些讨厌vi的人 simply 无法理解这个模式,以及命令模式和插入模式之间存在差异的事实。
我们已经告诉过你,像w这样的命令会移动一个单词。我们在告诉你这一点时,实际上有点欺骗了。并不存在像w这样的命令。w是一个对象规范,而不是一个命令。对象规范是在没有像d这样的显式操作符的情况下给出的。在这种情况下,vi 使用隐式默认操作符。而这个操作符是移动。
每当你使用没有操作符的对象规范时,都会使用移动操作符。因此,对象规范会退化为移动命令。以下是所有对象规范的列表和摘要。从逻辑上讲,你可以将它们与操作符结合使用,或者在独立使用时用于四处移动。你已经见过其中的一些了。
- }
- 直到下一个段落结束的所有内容。
- {
- 直到上一个段落结束的所有内容。
- ]]
- [直到下一个节结束的所有内容。]
- [[
- [直到上一个节结束的所有内容。]
- )
- 直到下一个句子结束的所有内容。
- (
- 直到上一个句子结束的所有内容。
- [数字]G
- 直到第数字行。如果省略了数字,则为文件中的最后一行(不是第一行)。第一行可以表示为1G代替。
- [数字]H
- 当前屏幕上第一行之后的数字行。如果未给出数字,则为屏幕上的第一行。
- [数字]L
- 当前屏幕上最后一行之前的数字行。如果未给出数字,则为屏幕上的最后一行。
- M
- 屏幕的中间行。
- j
- 当前行向下移动一行。
- k
- 当前行向上移动一行。
- _
- (下划线) 整个当前行。
- 0
- (数字 0). 向后移动到行的第一列。与1|(非0|).
- ^
- 向后移动到第一个非空白字符。
- $
- 向前移动到行尾。
- [数字] |
- 当前行的第数字列。如果未给出数字,则使用第 1 列。
- t字符
- 当前行中下一个字符出现之前的位置。
- T字符
- 当前行中下一个字符出现之后的位置。
- f字符
- 当前行中下一个字符出现的位置。
- F字符
- 当前行中上一个字符出现的位置。
- ;
- 重复最后一个t, T, f, 或者F这样的命令。
- ,
- 重复最后一个t, T, f, 或者F命令,但在相反方向。
- +
或者
- <CR>
- 移动到下一行的第一个非空白字符。
- -
- 移动到上一行的第一个非空白字符。
- w
- 向前移动到下一个单词的开头。
- e
- 向前移动到下一个单词的结尾。
- b
- 向后移动到上一个单词的开头。
- h
或者
- <BS>
- 左边的字符。
- l
或者
- <SPACE>
- (小写字母 L 或空格) 右边的字符。
- /模式/
- 向前移动到模式模式的第一个匹配项的开头。
- ?模式?
- 向后移动到模式模式的第一个匹配项的开头。
- <n>
- 重复最后一个/或者?.
- <N>
- 重复最后一个/或者?在相反方向。
- <%>
- 移动到下一个匹配的 (, {, 或 [。
前面列出的对象可以作为操作符的参数。如果未给出操作符,则使用默认的移动操作符。vi 中的操作符数量惊人地少——总共十个。以下是操作符的列表。
需要更好的描述,其中一些将在本模块的后面部分单独进行描述。
- c
- 更改 - 更改所指向的对象。实际上,文本会被输入的内容替换。
- d
- 删除 - 删除所指向的对象。被删除的文本会被放置到撤销缓冲区中。
- y
- 粘贴 - 将所指向对象的文本复制到缓冲区中。
- <
- 左移 - 对象参数只能是那些指向行的对象缩进和移位。
- >
- 右移 - 对象参数只能是那些指向行的对象缩进和移位。
- !
- 感叹号 过滤 - 通过外部程序过滤行。对象只能是那些指向行的对象过滤(存根)。
r, s,
- x
- 删除字符。使用d 操作符删除字符以外的对象。
- ~
- 切换光标位置字符的大小写。大写字母将变成小写字母,小写字母将变成大写字母。
在输入操作符时,有两种特殊形式。
- 输入大写字母,而不是小写字母。例如Y代替y,以及
- 重复该字符。例如yy代替y.
vi 是在终端或调制解调器连接速度很慢的时代编写的。因此,vi 使用了几种优化技术来限制重绘整个屏幕的需要。在这种情况下,vi 以前会显示以特殊标记开头的行。现代 vi 很少需要这种性能优化,但它们仍然有显示这种行的习惯。
使用两种特殊的标记。
~line
以“~”开头的行表示该行在文件末尾之后(不存在)。例如,在空文件或新文件中启动 vi 时,就可以观察到这种情况。
@line
该行只在屏幕上,不在文件中。这会发生在删除行时。如果启用了换行(默认值),则对于太长而无法在屏幕上一次显示的所有行也会发生这种情况。
vi 支持文本行的自动缩进,还提供手动缩进的命令。这在编辑程序源代码时很有用。在许多编程语言中,使用缩进以提高源代码的可读性是一种常见的惯例。
选项shiftwidth(sw) 决定缩进使用多少空格。例如。
<ESC>:set shiftwidth=4<CR>
或者
<ESC>:set sw=4<CR>
告诉 vi 使用四个空格进行缩进。
选项 [no]autoindent(ai) 告诉 vi 是否使用自动缩进。自动缩进通过以下命令打开
<ESC>:set autoindent<CR>
或者
<ESC>:set ai<CR>
它通过以下命令关闭
<ESC>:set noautoindent<CR>
或者
<ESC>:set noai<CR>
命令模式
[edit | edit source]移动行使用 < 和 > 命令。< 将文本向左移动一个shiftwidth(取消缩进),而 > 将文本向右移动一个shiftwidth(缩进)。可以影响的行数以 vi 的典型方式指定。但是,只能使用标识行的 对象,而不能使用标识单词或单个字符的对象。
例如。
>G
将从当前行到文件结尾的所有行向右移动。
或者
<}
将从当前行到段落结尾的所有行向左移动。当然,移位命令可以与%一起使用,它表示下一个左括号。例如,要将包含当前光标位置的行(直到第一行与匹配的 (、{ 或 [ 相匹配)向左移动一个,可以键入
<%
与所有命令一样,也可以指定行数
- [number]<<
或者
- <[number]<
- 移动从当前行开始的number 行,向左移动一个shiftwidth(取消缩进)。如果未给出number,则假定为 1 - 这会导致将当前行向左移动。
- [number]>>
或者
- >[number]>
- 移动从当前行开始的number 行,向左移动一个shiftwidth向右移动一个(缩进)。如果未给出number,则假定为 1 - 这会导致将当前行向右移动。
< 和 > 命令也可以与标记一起使用。在这种情况下,对标记的引用放在命令的两个字符之间
- <'m<
- 将从标记m 到包括当前行的所有行向左移动。
- >'m>
- 将从标记m 到包括当前行的所有行向右移动。
插入模式
[edit | edit source]- ^t
- 向右移动shiftwidth。请注意,使用 <TAB> 键而不是^t是一个常见的错误。<TAB> 插入一个 Ctrl-I 字符并移动到下一个tabstop 的倍数,而不是shiftwidth。因此,只有当tabstop 和shiftwidth 设置为相同的值时,<TAB> 才能工作。
- 由于将tabstop 设置为 8 以外的值不是一个好主意,因此,只有当shiftwidth 也设置为 8 时,才能使用 <TAB> 代替^t进行缩进。
- ^d
- 在自动缩进模式下,向后缩进一个shiftwidth。例如,如果自动缩进打开,并且想要输入以下文本
if(true) { printf("done"); // start sw indent return; } // bracket moved back to the left
- 将键入
if(true) {<CR> ^tprintf("done"); // start sw indent<CR> return;<CR> ^d} // bracket moved back to the left<CR>
还有一些^d的特殊变体
- ^^d
- (字母^ 后跟 Ctrl-D)。当在新的行上首次键入此命令时,所有自动缩进都会被清除(插入点将移动到行的开头)。然后在下一行继续自动缩进。
- 例如,要在使用自动缩进时输入以下文本
an indented paragraph another line in the indented paragraph .F roff formating commands have to start at column one with a '.' more text in the indented paragraph
将键入
^tan indented paragraph<CR> another line in the indented paragraph<CR> ^^d.F roff formating commands have to start at column one with a '.'<CR> more text in the indented paragraph<CR>
- 0^d
- (数字0 后跟 Ctrl-D)。清除所有自动缩进(将光标移动到行的开头),并关闭自动缩进,直到手动缩进文本(使用^t).
- 例如,要在使用自动缩进时输入以下文本
INTEGER FUNCTION FAC(N) FAC = 1 DO 100 I = 2, N FAC = I * FAC C C PROVIDE LABEL TO END LOOP C A HINT FOR THOSE GRASSHOPPERS: THIS IS FORTRAN CODE :-) C 100 CONTINUE RETURN END
- 将键入
<ESC>:set sw=5<CR> o^tINTEGER FUNCTION FAC(N)<CR> FAC = 1<CR> DO 100 I = 2, N<CR> ^tFAC = I * FAC<CR> 0^dC<CR> C PROVIDE LABEL TO END LOOP<CR> C A HINT FOR THOSE GRASSHOPPERS: THIS IS FORTRAN CODE :-)<CR> C<CR> 100 CONTINUE<CR> ^tRETURN<CR> END<CR>
模型行
[edit | edit source]模型行是文本文件中的行,当打开此类文本文件时,vi 会对其进行特殊解释。当modeline (ml)(在某些版本的 vi 中也称为modelines)选项打开(例如,在用户的.exrc文件中),vi 会扫描每个打开文件的首尾五行,以查找以下形式的文本
unrelated text vi:command: more unrelated text
或者
unrelated text ex:command: more unrelated text
从这些行中获取每个command 并按用户键入的方式执行。模型行标记前面的任何文本(vi或者ex)或关闭标记后面的任何文本:在模型行解释中被忽略。这可以用于将模型行放在注释中,如果它们用于某些编程源代码。
这是一个示例 Java 源代码文件。它在第二行和第三行包含模型行,位于 Java 注释中
/* * vi:set sw=4 ai: * vi:set showmatch: */
package gnu.freesoftware; public class Interpreter { public Interpreter() ... ...
当模型行打开,并且打开此文件时,shiftwidth (sw)设置为 4,autoindent (ai)打开,并且showmatch (sm)选项也会打开。没有特别的理由说明为什么要使用两个模型行上的两个set命令,除了演示在首尾五行中找到的所有模型行命令都将被执行,而不仅仅是第一个。
模型行可以用于玩一些实际的玩笑。例如,包含模型行的文件
vi:q!:
立即关闭编辑器,并且只要模型行打开,就无法编辑文件。
如果模型行弄乱了系统文件,则会变得非常危险。例如,如果 Unix 系统的超级用户(管理员)打开了模型行,并且被诱骗打开包含以下模型行的文件,则重要的 Unix 密码文件将被打开文件的内容覆盖
vi:2,$w! /etc/passwd: root:A shiny new root password:0:0:System Administrator:/:/bin/sh anotheruser:Another shiny new password:1:0:Just another user:/home/anotheruser:/bin/sh
因此,模型行只能在受控环境中打开。这很遗憾,因为原则上,文件能够为编辑器提供最适合编辑该文件的配置是一个好主意。
模型行还存在一些其他问题。经典的 vi 版本在找到模型行时始终将文件的状态设置为已修改,即使没有对文件进行任何编辑。这会迫使用户使用以下命令退出编辑器:q!而不是:q。如果改为使用ZZ退出,则文件将被写入。这会导致像make 这样的工具认为文件已更改,即使实际上没有更改。
.exrc 配置文件
[edit | edit source]此模块是一个 存根。您可以通过 修复它 来帮助 Wikibooks。 首先
.exrc 文件是包含 vi(和 ex)配置数据的文件。此类文件中的数据格式是 ex 命令的格式,没有前导 ':'(列)。通常,.exrc 文件用于加载一些默认映射(map 和 map! ex 命令)或定义特定默认值。例如,以下 .exrc 文件将在启动 vi 时设置自动缩进和 shiftwidth
set ai set sw=4
通常,.exrc 文件放置在用户的 home 目录中。由于文件名以 '.' 开头,因此该文件在类 Unix 操作系统下是隐藏的。也可以在其他目录中放置 .exrc 文件。vi 可以读取从其启动的当前目录中的 .exrc 文件。但是,此功能被认为是一种安全风险,默认情况下已关闭。它被认为是一种风险,因为与模型行所描述的相同的笑话也可以对 .exrc 文件进行。用户 home 目录中的 .exrc 文件被认为是安全的,因为在正确配置的 Unix 系统上,只有特定用户应该对其具有写访问权限。
在使用经典的 vi 和 .exrc 文件时,应该注意三件事
- .exrc 文件不能包含空行。经典的 vi 会因这些行而出现各种神秘的错误消息。
- 没有官方的方式在 .exrc 文件中放置注释。但是,从一开始,以下 hack 就被使用并且已知有效:以 "(引号字符)开头的行会被 vi 忽略。
- 经典的 vi 对 map 和 map! 命令非常挑剔。从各个方面来说都应该起作用的定义可能会触发奇怪的错误消息。这是由于经典的 vi 对此类定义的解析器和解释器有限。将 map 或 map1 命令拆分为几个较小的命令有时可以帮助解决问题。
许多克隆通过允许 .exrc 文件中的空行,以及通过正式指定 " 作为注释字符,放松了这些规则。此外,好的克隆应该不会遇到 map 或 map! 规范的问题。
" " This is a comment in an .exrc file " A .exrc file must not contain empty lines, so " comment lines need to be used to separate entries " set sm set sw=8 " set wm=8 " " map 'g' to go to begin of file map g 1G " rcs check-out (/co) and check-in (/ci) map /co :w! %.co.bak^M:!co -l %^M:e! map /ci :w^M:!ci -u %^M:e!^M " " Abbreviations ab Lx Linux
标签
[edit | edit source]概述
[edit | edit source]vi 可以使用所谓的标签文件(或标签)来允许快速导航(跳转)到一组文件中的“有趣”信息。最常见的用法是在源代码文件中进行导航。例如,从某个函数的使用跳转到该函数的定义,可能在另一个文件中。
该机制相对简单。您告诉 vi 跳转到特定标签。vi 会查找包含该标签的文件,打开该文件并跳转到该文件中标签的位置。为了查找文件和标签的位置,vi 会查阅一个 *标签文件*。*标签文件* 包含标签索引。标签是可以在标签文件中找到索引条目的项目(例如某些编程语言对象)。当 vi 被要求跳转到特定标签时,vi 会查找该标签的索引条目,并使用该信息跳转到特定项目。
为了使用此功能,首先必须创建一个标签文件或一组标签文件,其中包含所有潜在有趣项目的条目。然后需要将这些标签文件或文件告知 vi - 如果不使用默认文件名。例如,这可以通过在.exrc文件中包含适当的命令来完成。
现代 IDE 提供类似的导航功能,但无需单独构建标签文件。IDE 会即时构建必要的索引或使用快速的暴力全文本搜索算法。对于 vi 来说,创建标签文件的额外步骤在现代标准中是令人厌烦的。不过,vi 的标签文件系统仍然可以工作,并且可以使用。
标签文件格式、创建和 ctags(1)
[edit | edit source]创建标签文件通常需要使用一个工具来分析输入文本文件(例如编程源代码)并为在输入文本文件中找到的每个感兴趣的项目生成条目。最常用的工具称为 ctags(1),它是标准的 Unix 程序。几个 vi 克隆自带了 ctags 的版本,有时称为不同的名称。
ctags 了解多种编程语言的语法,并为函数名、宏定义等项目生成索引信息。
如果 ctags 不可用,或者 ctags 的可用版本不支持使用的编程语言,也可以使用 awk(1)、sed(1) 或 perl(n) 等文本处理工具和一些巧妙的脚本生成标签文件,因为标签文件是 ASCII 文件。
标签文件中的条目通常如下所示
tag-name<TAB>file-name<TAB>ex-command
- tag-name
- 项目的名称。例如函数名或宏名。
- file-name
- 包含 *tag-name* 项目的文件的名称
- ex-command
- 一个 ex 编辑器命令,指示如何在文件中定位该项目。这可以是任何 ex 命令。但两种类型的 ex 命令最合理
- 在简单的形式中,*ex-command* 是一个行号,这实际上是一个有效的 ex 命令。
- 但是,通常最好使用搜索模式,例如/tag-name/这提供了一些灵活性,如果文件稍后被编辑。它减少了必须重建标签文件的次数,因为某些东西在文件内部移动了。ctags 也主要生成模式搜索命令,而不是行号。
通常,vi 克隆允许对这种格式进行一些扩展。查看特定的文档。
标签文件应按字母顺序排序以加快操作速度。如果无法做到这一点,可以使用 vi 的 -S 命令行选项。
通常不建议通过手动运行 ctags 或自己的工具来生成标签文件。相反,标签文件的构建通常更好地集成到软件构建系统中。对于 Unix 来说,这意味着使用 *Makefiles*。通常,用于生成标签文件的 make(1s) 目标称为 *tags*,因为这是要创建的标签文件的名称
# Makefile snippet SRCS = ... # all source code tags: $(SRCS) ctags -dt $(SRCS)
Ex 命令
[edit | edit source]默认情况下,vi 在名为tags的文件中查找所有标签。可以使用以下 ex 命令更改此文件名。事实上,可以指定多个文件名。它们都加载以查找标签。该命令最好放在特定于项目的.exrc文件中包含适当的命令来完成。
- :set tags=filename[\ filename ...]<CR>
- 设置包含标签信息的 filename 的名称。如果要提供多个标签 *filename*,该命令的语法在不同的 vi 版本之间略有不同。文件名必须用“\ ”(反斜杠空格)或“;”(分号)分隔。
可以通过以下 ex 命令导航到标签。还有一个 vi 命令可以执行此操作。
- :ta tag-name<CR>
- 或者
- :tag tag-name<CR>
- 在标签文件(s)中查找 *tag-name*,打开索引条目中命名的文件并执行索引条目中的 *ex-command*。这将有效地将用户定位到定义符号 *tag-name* 的文件和位置。该命令还会记住标签堆栈上的当前文件和位置。
vi 中的 EX 命令
[edit | edit source]Ex 是一个行编辑器,是屏幕编辑器 vi 的基础。Ex 命令对当前行或文件中的一系列行起作用。
Ex 命令的语法
:[address] command [options]
“:” 指定一个 Ex 命令。
地址
“地址”指定作为命令对象的行号或行范围。如果没有给出地址,则当前行是命令的对象。
地址范围可以通过以下任一方式在 Ex 命令语法中指定。
语法 | 范围 |
---|---|
:% | 文件中的所有行。 |
:1,$ | 文件中的所有行。 |
:^,$ | 文件中的所有行。 |
:X,Y | 从行号 X 到行号 Y 之间的所有行。 |
:.,.+n | 从当前行到下一行 n 行的所有行。 |
:.,.-n | 从当前行到上一行 n 行的所有行。 |
:X;Y | 从行号 X 到行号 Y,将当前行设置为行号 X。 |
:X,+n | 从行号 X 到当前行后的下一行 n 行的所有行。 |
:X,-n | 从行号 X 到当前行前的上一行 n 行的所有行。 |
:X | 行号 X。 |
:. | 当前行。 |
:$ | 文件的最后一行。 |
:0 | 文件的首行。 |
:X-n | 在行号 X 之前 n 行的行。 |
:X+n | 在行号 X 之后 n 行的行。 |
:'b | 用字母 b 标记的行。 |
:' | 标记的行。 |
:/word | 包含模式 word 的下一行。 |
:?word | 包含模式 word 的上一行。 |
命令
命令 | Ex 语法 | 操作 |
---|---|---|
替换 | :%s/str1/str2/g | 将整个文件中指定的地址范围内的 str1 替换为 str2。 |
复制和粘贴 | :t8 | 复制当前行并在行号 8 后粘贴。 |
复制和粘贴 | :9t11 | 复制第 9 行并在行号 11 后粘贴。 |
复制和粘贴 | :5,8t10 | 复制第 5 行到第 8 行并在行号 5 后粘贴。 |
复制和粘贴 | :10,14co20 | 复制第 10 行到第 14 行并在行号 20 后粘贴。 |
移动和粘贴 | :m8 | 剪切当前行并在行号 8 后粘贴。 |
移动和粘贴 | :9m11 | 剪切第 9 行并在行号 11 后粘贴。 |
移动和粘贴 | :5,8m10 | 剪切第 5 行到第 8 行并在行号 5 后粘贴。 |
将/复制到命名缓冲区中。 | :3,10y p | 将第 3 行到第 10 行之间的文本复制到缓冲区 p(单个小写字符)中。 |
将/复制。 | :3,10y | 将第 3 行到第 10 行之间的文本复制到临时缓冲区中。 |
粘贴/放置 | :10p | 将临时缓冲区中的文本粘贴到第 10 行。 |
粘贴/放置 | :p | 将临时缓冲区中的文本粘贴到当前行。 |
粘贴/放置 | :+10p | 将临时缓冲区中的文本粘贴到当前行后的第 10 行。 |
写入/保存文件 | :w! | 保存当前文件。 |
写入/保存文件 | :w fname | 将当前文件保存为 fname。类似于 Windows 操作系统中的“另存为”。 |
写入/保存文件 | :15,30w fnew | 将当前文件中的第 15 行到第 30 行保存到名为 fnew 的新文件中。 |
写入/保存文件 | :15,30w >> fexist | 将当前文件中的第 15 行到第 30 行追加到名为 fexist 的文件中。 |
写入/保存文件 | :x! | 强制保存并退出当前文件。 |
退出文件 | :q | 退出当前文件。 |
退出文件 | :q! | 强制退出当前文件,不保存。 |
编辑/刷新 | :e! | 刷新 - 丢弃未保存的更改。 |
编辑 | :e fname | 编辑名为 fname 的文件,而不退出 vi。 |
编辑 | :n | 编辑下一个文件,而不退出 vi。 |
编辑 | :p | 编辑上一个文件,而不退出 vi。 |
编辑 | :rew | 编辑上一个文件,而不退出 vi。 |
插入文件 | :r fname | 在当前光标位置插入名为“fname”的文件中的所有文本。 |
读取/插入 | :r! command | 在当前光标位置插入命令的输出。 |
读取/插入 | 10:r! command | 在第 10 行插入命令的输出。 |
插入文件 | :r fname | 在当前光标位置插入名为“fname”的文件中的所有文本。 |
插入文本 | :45i! | 在第 45 行设置插入模式。 |
追加文本 | :45a! | 在第 45 行设置追加模式。 |
删除行 | :d | 删除当前行。 |
删除行 | :45d | 删除第 45 行。 |
删除行 | :.,.+15d | 删除当前行和接下来的 15 行之间的所有行。 |
删除行并放入缓冲区 | :.,.+15d f | 删除当前行和接下来的 15 行之间的所有行,并将它们放入名为 f 的缓冲区。 |
标记一行 | :10ma f | 用单个小写字母 f 标记第 10 行。稍后使用 'f 返回标记位置。 |
Shell 命令 | 10,15:! command | 在 shell 中执行命令。将第 10 行和第 15 行之间的文本作为命令的标准输入,并用输出替换这些行。 |
查看 | :10z | 设置视图,将第 10 行放在屏幕顶部。 |
查看 | :10z+ | 设置视图,将第 10 行放在屏幕顶部。 |
查看 | :10z- | 设置视图,将第 10 行放在屏幕底部。 |
查看 | :100z. | 设置视图,将第 100 行放在屏幕中央。 |
查看 | :100z^ | 设置视图,将第 100 行放在屏幕中央,并将当前行设置为第 100 行。 |
查看 | :10z+ 5 | 设置视图,将第 10 行放在屏幕顶部,并显示第 10 行之后的 5 行。 |
状态 | :f | 在屏幕底部显示当前位置和文件名。它还指定自文件打开以来是否对文件进行了任何更改。 |
选项
选项 | 操作 |
---|---|
! | 指定命令必须强制执行。 |
目标 | 指定粘贴文本的行号。与复制和移动命令一起使用。 |
计数 | 指定命令重复的次数。该数字始终在命令之后。 |
fname | 指定对象是一个名为“fname”的文件。 |
Vi 命令
[edit | edit source]可以使用以下 vi 命令导航到标签
- ^]
- 取光标位置处的 tag-name,在标签文件(多个)中查找它并导航到它,类似于:taex 命令。该命令还会记住标签栈上的当前文件和位置。
以下命令使用标签栈返回到之前的位置。旧版本的 vi 未实现它
- ^T
- 从标签栈中获取之前的位置和文件并返回。数据将从文件中删除。
命令行
[edit | edit source]也可以使用标签名而不是文件名启动 vi。请参阅 -t 命令行选项。
Shell 转义
[edit | edit source]在 vi 中工作时,可能需要运行另一个操作系统命令。在如今,这不是什么大问题。可以打开另一个终端窗口并随意操作。但是,在使用 vi 时,这并非必要。vi 与许多旧的交互式 Unix 工具一样,包含在编辑器中运行操作系统命令或启动命令行解释器(shell)的功能。这可以追溯到没有图形用户界面,并且像 vi 这样的编辑器会占用终端的整个屏幕(当然是指真正的终端,而不是终端模拟器)的时代。能够从 vi 中运行命令可以省去先退出编辑器才能查看某些内容的麻烦,例如,查看手册页。
此外,vi 还提供将其他命令的文本输出直接插入正在编辑的文本中的功能。
Ex 命令
[edit | edit source]实际上,在 vi 中运行另一个命令的编辑器命令是作为 ex 命令实现的。也就是说,它们以命令模式下的熟悉“:”开头。
要从 vi 中执行一个命令,可以键入
:!command<CR> <CR>
在 command 结束时,必须按回车键(上面显示的第二个 <CR>)才能返回 vi。然后 vi 重新绘制屏幕并继续从停止的地方进行编辑。
要重复最后一个 command,只需键入
:!!<CR> <CR>
可以使用:!!将内容追加到之前的命令,后面加上要追加的内容。例如,以下两个命令中的第二个
:!ls<CR> <CR> :!! | more<CR> <CR>
实际上等同于
:!ls | more<CR> <CR>
(注意,ls 是 Unix 命令,用于列出目录,more 是 Unix 命令,用于分页输出,因此它不会简单地从屏幕上滚动)。
一旦将某些内容追加到命令,它就会成为最后一个记住的命令的一部分。因此,在上面的示例中,另一个
:!!<CR> <CR>
将等同于
:!ls | more<CR> <CR>
而不是
:!ls<CR> <CR>
可以在 shell 转义中使用两个占位符来表示当前文件名或之前编辑的文件名
- %
- 是当前文件名的占位符,
- #
- 是之前编辑的文件名的占位符。
例如,如果正在编辑一些 shell 脚本并想尝试运行它,可以键入以下命令来保存文件(:w),将文件属性设置为可执行(!chmod ...),并运行它(!%):
:w<CR> :!chmod 755 %<CR> <CR> :!%<CR> <CR>
如果文件名例如是 script.sh,则上述操作相当于键入
:w<CR> :!chmod 755 script.sh<CR> <CR> :!script.sh<CR> <CR>
除了从 vi 中运行命令之外,还可以从 vi 中启动 shell。vi 有一个自己的命令用于执行此操作,该命令会查找用户的默认 shell(例如,Bourne shell 或 C shell)并启动它。请务必注意,将启动一个新的 shell。用户不会返回到启动 vi 的 shell。该命令称为 :sh,它可以按如下方式使用
<ESC>:sh<CR> $ #shell commands, when done exit shells: $ exit<CR>
Vi 命令
[edit | edit source]可以将当前正在编辑的文本的全部或部分内容通过外部程序过滤。然后用外部命令的输出替换原始文本。
此功能的经典示例是使用 Unix 文本格式化程序 fmt。vi 本身没有任何特定的格式化功能,但是,通过从 vi 中运行文本或部分文本,使用外部格式化程序,可以轻松实现所需的格式化。
用于过滤文本的 vi 命令是!(注意,与 ex shell 转义命令不同,没有前导的:). !遵循通常的 vi 命令格式。因此可以指定它应该适用的范围。例如!!表示过滤当前行,或者!}表示过滤当前段落。
该!vi 命令后面必须跟用于过滤的外部程序的名称。例如,要使用前面提到的 Unix 文本格式化程序 fmt 格式化当前段落,可以键入
!}fmt<CR>
!也可以用于将某些外部命令的输出插入到当前编辑的文本中。为此,首先创建一个新的空行(例如,使用o),然后使用!!用命令的输出替换空行。例如,
o<ESC>!!ls<CR>
将在 Unix 中将当前目录中的文件列表包含到文本中。
从缓冲区执行命令
[edit | edit source]此模块是一个 存根。您可以通过 修复它 来帮助 Wikibooks。
- @b
- 执行存储在缓冲区 b 中的命令。
面向程序员的 vi
[edit | edit source]经典的 vi 提供了许多对程序员有用的功能。vi 是由程序员为程序员制作的——但在编程方式不同的时代。根据今天的标准,经典 vi 的编程支持不太好,但当然仍然可以使用。而且,使用 vi 编辑编程代码仍然比使用任何 ...pad 编辑器(如 notepad(Windows)或 dtpad(CDE/Motif))更方便。vi 可能在 Unix 系统上效果最佳,因为 Unix 附带了许多文本过滤器,并且可以轻松地用脚本编写额外的专用过滤器。
vi 中对程序员有用的功能有
自动缩进和手动行移位
[edit | edit source]请参阅 缩进和移位
模型行
[edit | edit source]模型行用于设置每种语言的默认值——如果安全性不是问题(请参阅 模型行)
参见 标签
参见 Shell 转义
- 使用 Shell 转义的一种方法是在 vi 中运行 makefile 或编译器。一般来说,在尝试编译文件之前先保存当前文件是一个好主意。
<ESC>:w<CR> :!make<CR>
or <ESC>:w<CR> :!cc %<CR>
and afterwards <ESC>:w<CR> :!!<CR>
- 另一种方法是通过外部命令过滤源代码,例如通过特定语言的注释格式化程序。例如,以下命令将通过名为 recomment 的外部注释格式化程序过滤当前段落(不是标准的 Unix 程序,但可以作为单独的脚本使用)。
!}recomment
- 参见 [1] 获取适用于 Unix 的 recomment 脚本。
vi 可以使用文件列表启动。
vi file1 file2 file3 ...
结合其他 Unix 功能,如文件匹配,这可能是一个强大的功能。例如,要打开目录中的所有 C 源代码,包括头文件(.h),可以使用以下命令
vi *.[ch]
或者,要查找包含特定关键字的所有文件并打开它们,可以使用类似的命令
vi `grep -l Keyword *.txt`
。
使用文件列表启动 vi 后,可以使用以下命令在列表中导航。
- :n
- next - 移动到文件列表中的下一个文件。
- :rew
- rewind - 倒回文件列表,并打开列表中的第一个文件。
像 vim 这样的 vi 克隆通常提供更多命令,例如在文件列表中后退一个文件。
- 使用#作为最后一个文件的名称,在两个文件之间切换。例如,在 C 源文件和相应的头文件之间切换。
:e x.c<CR> :e x.h<CR> some changes to x.h, then going back to x.c <ESC>:w<CR> :e#<CR>
- 使用以下命令在两个文件之间切换CTRL-^。这是被遗忘的 vi 命令之一。
Unix 上的 error(1) 程序可用于捕获来自编译器的错误消息,并在编辑器中从一条错误消息跳转到另一条错误消息。error 的工作方式过时了。它会解析来自编译器的错误消息,并将它们作为注释插入编译器检测到错误的源文件中。由于 error 使用###和%%%在源文件中标记错误消息,因此可以使用 vi 命令(如/和n.
进行导航。
- 使用 error 与 vi 有两种常见的方法。-v从 vi 外部,让 error 启动 vi。error 可以使用
$ cc *.c 2>&1 | error -v # Notes: # cc - the C compiler # *.c - all C files in the current directory # 2>&1 - Standard error output is redirected to normal standard output # | - the output is feed to error as input
- 标记在所有在编译期间产生错误的文件上启动 vi。:e!2. 从 vi 内部,在当前文件上。首先保存文件,然后尝试编译它,使用 error 处理潜在的错误消息,然后重新读取可能更改的源文件(/###:
first time <ESC>:w<CR> :!cc % 2>&1 | error<CR> :e!<CR> /###<CR>
and afterwards <ESC>:w<CR> :!!<CR> :e!<CR> /###<CR>
- ),最后使用
- 搜索第一个标记。
注意
error 是一种糟糕的解决方案,它会严重破坏源代码和版本控制系统!我们建议您至少尝试一次,并形成自己的看法。此外,请先查看 error 的手册页。像 vim 这样的 vi 克隆提供了一个更加合理系统。在这里,编辑器会执行编译器(或 make(1s)),并捕获编译器的输出。vim 会将信息记录在错误消息文件中。然后,vim 通过从错误消息中提取文件名和行号并跳转到这些位置来允许导航源代码。这与 IDE 提供的机制相同。宏和快捷方式[编辑 | 编辑源代码]和vi 提供:map:map!命令来定义有用的快捷方式和宏,以及
- ab
qqI//<Esc>jq places a comment at the beginning of a line and moves down
- 来提供缩写。
待办:提供一些此类宏?
这是(上面)您所说的宏吗?概述
nroff/troff 排版支持vi 支持编辑适用于 Unix 排版程序 nroff 和 troff 的文本文件。如今,这些排版程序最“常见”的用途可能是编写 Unix 应用程序的手册页(man)。
.SH "A SECTION HEADER" Some text making up the first paragraph in the section. More text in the paragraph. .PP A new paragraph has been started. More text in this second paragraph. .PP Yet another paragraph. .\" .\" A comment infront of the next section header .\" .SH "SECTION HEADER 2" Paragraph text.
编写 nroff/troff 输入文本文件的功能始终处于激活状态,没有需要打开的特殊 vi 模式或选项。由此可以推断出,vi 中并没有太多特定于 nroff/troff 的操作。实际上,vi 只提供简单的导航方式来在 nroff/troff 段落和节之间移动。然而,这些功能在编辑 nroff/troff 文件时有所帮助。nroff/troff 的文本文件格式很简单。普通文本和宏混合在一起,其中宏指示文本的格式。宏以第一列中的“.”开头,后面跟着一到两个字母的宏名称,以及可选的宏参数。包含一些宏的典型 nroff/troff 文本文件可能如下所示为了简化此类文本文件的导航,vi 了解节(上面示例中的.SH) 和段落(示例中的
.PP
<ESC>:w<CR> :!nroff -man % | more<CR>
选项
) 的常见宏名称,并提供命令来移动到下一个/上一个节。宏名称列表在 vi 中是可配置的。许多常见的 vi 功能在编辑 nroff/troff 文本时也有帮助。例如,使用 Shell 转义从 vi 中运行排版程序。以下命令将使用手册页宏格式化当前文件[编辑 | 编辑源代码]以下选项用于定义 vi 识别的 nroff/troff 宏名称。与所有选项一样,可以使用
:set option[=value]
- :set
- ex 命令更改它们。nroff/troff 的文本文件格式很简单。普通文本和宏混合在一起,其中宏指示文本的格式。宏以第一列中的“.”开头,后面跟着一到两个字母的宏名称,以及可选的宏参数。包含一些宏的典型 nroff/troff 文本文件可能如下所示, sections, vi 解释为节分隔符的宏名称列表。列表中的两个连续字符构成一个宏名称。通常,vi 的默认设置包含,以及.NH.H
sections=SHNHH HU
- .HU
- 或者
- 。因此,sections 选项的读取方式为
- paragraphspara, vi 解释为段落分隔符的宏名称列表。列表中的两个连续字符构成一个宏名称。vi 的默认设置通常包含, .SH, .IP, .LP, .QP, .PL.Ib
paragraphs=IPLPPPQPPLIbp
Vi 命令
.p。因此,paragraphs 选项的读取方式为
- ]]
- 在命令模式下,以下命令与处理 nroff/troff 文本相关。
- {
- 移动到上一个节。
- }
- 移动到下一个节。
移动到上一个段落。
- (
- 移动到下一个段落。
- )
- 为了完整起见,
学习 vi 编辑器: 熟悉 — 基本任务 — 使工作更轻松 — 高级任务 — 详细信息 — Vi 克隆 (Vim – 基本导航 – 模式 – 技巧和窍门 – 程序员需要了解的有用内容 – 增强 Vim – Vim 在 Windows 上 – VimL 脚本语言, Vile, BB vi) — vi 参考 |