Top

D9:配置和环境之二

vi

一个老笑话:
	游客:请问,怎么去卡内基音乐厅?
	纽约人:练习、练习、练习!
目录:

为什么学习vi


一点背景

第一版vi出现在1976年,由加州大学伯克利分校的Bill Joy(原名William Nelson Joy,威廉·纳尔逊·乔伊,开发了BSD系统。1982年他与其他人一起创办了Sun。)编写。
vi的名字源于“visual”(视觉),因为其目的是允许在移动光标的视频终端上进行编辑。
在此之前,由line editor(行编辑器),一次只对一行文本进行操作。如果要指定更改,必须告诉行编辑器转到特定行并描述要进行的更改。
vi实际上包含一个强大的行编辑器ex,可以在使用vi时使用行编辑命令。

大多数Linux发行版不包含真正的vi,而是包含由Bram Moolenaar编写的vim。
vim是对传统Unix vi的重大改进。

开始和停止vi

要开始vi,只需要在命令提示符下简单的输入vi并按回车即可。
要退出vi,只需在vi的命令模式中输入:q(注意,冒号为命令的一部分)然后按回车即可回到命令提示符。

如果由于某些原因(通常是文件被修改但是没有保存)无法退出vi,可以使用:q!命令强制退出。

如果迷失在vi中,可尝试按Ees键两次找到自己在哪。


编辑模式

进入vi后,屏幕上可以看到若干以~开头的行,这些行实际上并不存在。
vi是一种模态编辑器(modal editor),当vi开始后,它首先进入命令模式(command mode)。在此模式中,几乎所有键都是命令,切记要谨慎。

进入编辑模式

如果要向文件添加内容,首先要进入插入模式(insert mode)。只需在vi的命令模式中输入字母i,可以在vi左下角看到:
-- INSERT --
然后就可以输入任意字符了。
输入完成后,按Esc键退出插入模式回到命令模式。

保存工作

要保存对文件的变更,必须在命令模式输入可执行命令(ex command)。这些命令以冒号开头。
冒号后面加w然后按回车,可以将文件写入存储介质:
:w
vi会反馈一些信息,例如:
"foo.txt" [New] 1L, 46C written
vim文档中,将命令模式称为normal mode,而把ex命令称为command mode。

移动光标

在命令模式下,vi提供了大量的移动命令,其中一些命令与更少的用户共享。下表是一个子集:
移动光标
l或右箭头 向右一个字符
h或左箭头 向左一个字符
j或下箭头 向下一行
k或上箭头 向上一行
0 到当前行开头
^ 到当前行第一个不是空白的字符
$ 到当前行尾
w 到下一个单词或标点符号的开头
W 到下一个单词的开头,忽略标点符号
b 到上一个单词或标点符号的开头
B 到上一个单词的开头,忽略标点符号
Ctrl-f或下翻页 向下一页
Ctrl-b或上翻页 向上一页
numberG 去第munber行的行首。例如1G移动到文件的第一行头部
G 到文件的最后一行行首
之所以使用h、j、k、l来移动光标,是因为早期不是所有的视频终端都有箭头键。
vi中许多命令都可以用数字做前缀,通过在命令前面加一个数字,可以指定执行命令的次数,例如,5j使光标向下移动5行。

使用:set nu可以显示行号,使用:set nonu取消显示行号。

基础编辑

大多数编辑包括一些基本操作,如插入文本、删除文本以及通过剪切和粘贴来移动文本。
在命令模式下按u键,可以撤销上次做的更改(对于vi,u只能回退一个命令,而vim可以回退更多个)。

追加文字

vi提供了多种方式进入插入模式,比如:

新开一行

另一个进入插入模式的方法是新开一行。此方法可以在两行之间插入一个空行,并进入插入模式。两种实现方法:

删除文字

命令 删除
x 当前字符
3x 当前字符开始的3个字符
dd 当前行
5dd 当前行开始的5行
dW 从当前光标位置到下一个单词的开头
d$ 从当前光标到当前行尾
d0 从当前光标到当前行首
d^ 从当前光标到本行第一个不是空白的字符
dG 从当前行到最后一行
d20G 从当前行到文件的第20行(如果数字超过了实际的行数,则什么都不执行)

剪切、复制、粘贴文字

命令d不仅仅用来删除文本,也可以用来剪切文本。每次使用d命令时,被删除的内容被复制到剪贴板,使用p命令可以将它们粘贴到当前光标后,或使用P命令将它们粘贴到当前光标前。
y命令用来复制文本,与d命令用来剪切文本的方式大致相同。
命令复制
yy 当前行
5yy 当前行和下4行
yW 从当前光标位置到下一个单词的开头
y$ 从当前光标位置到当前行的末尾
y0 从当前光标位置到行首
y^ 从当前光标位置到行中第一个非空白字符
yG 从当前行到文件尾
y20G 从当前行到文件的第20行

加入行

vi对行的概念相当严格。通常情况下不可能将光标移动到行尾并删除行尾字符以将一行与其下一行进行连接。(也就是不能删除行尾的回车换行符)
vi提供了一个特定的命令J(不是j,j是用来移动光标的)来连接行。
连接行相当于将原两行之间的回车换行符替换成了空格。

查找和替换

vi能够根据搜索将光标移动到指定位置。搜索的范围可以是一行或整个文件。还可以在用户确认或不确认的情况下执行文本替换。

在行内查找

f命令搜索一行,并将光标移动到搜索到的字符上。
例如fa命令会将光标移动到当前行中字符a上,按分号键可以重复向后搜索。
f命令只能搜单个字符。

在文件中查找

/命令用于在正文件中搜索单词或短语。
输入/后,屏幕底部会出现一个/,在它后面输入要搜索的单词或短语,然后按回车,光标将移动到下一个包含搜索字符串的位置。使用n命令可以继续搜后后面的内容。
搜索至文件尾后,系统会问是否从头再搜。
vi允许使用正则表达式。

全局查找和替换

vi使用ex命令对一系列行或整个文件执行搜索和替换操作(vi中称为substitution)。例如,将文件中所有的“Line”改为“line”,可以使用以下命令:
:%s/Line/line/g
以上每个元素的意义:
元素 含义
: 以冒号开始ex命令
% 指定操作范围
%是从第一行到最后一行的快捷方式。也可以用1,5来指定从第一行到第五行。或者1,$表示从第一行到最后一行。
如果省略了行的范围,则仅再当前行上执行操作。
s 指定操作
在本例中,它是替换(substitution)。
/Line/line/ 指定搜索模式和替换文本
/Line是搜索Line的意思;/line/是替换成line的意思
g 表示全局(global)
即对行中搜索字符串的每个实例执行搜索和替换。如果省略,则只替换每行上搜索字符串的第一个实例。
如果需要用户确认,可以在以上命令末尾添加一个c,例如:
:%s/Line/line/gc
vi遇到匹配的情况时,会提问:
replace with line (y/n/a/q/l/^E/^Y)?
确认字母分别代表:
动作
y 进行替换
n 跳过这次
a 同意本次以及后续所有的
q或者Esc 退出替换
l 同意本次,然后退出。是last的简写
Ctrl-e,Ctrl-y 分别向下和向上滚动,这有助于查看拟替代的上下文
匹配替换的示例:
语句 含义
:s/old/new 将当前行匹配到的第一个old替换为new
:s/old/new/g 将当前行匹配到的所有old替换为new
:%s/old/new 将文档中每一行匹配到的第一个old替换为new
:%s/old/new/g 将文档中所有old替换为new

编辑多个文件

以下命令可以同时打开多个文件:
vi file1 file2 file3 ...
freebsd中的vi似乎不行,vim就可以 以上命令会将file1显示在屏幕上。

在文件间切换

:bn切换到下一个文件;:bp切换到上一个文件。
vi强制执行一个策略,如果当前文件有未保存的更改,则会阻止切换文件。要强制切换文件并放弃更改,可以添加感叹号。

vim提供了一些ex命令,便于管理多个文件。
:buffers命令可以查看正在编辑的文件列表:
:buffers
  1 %a "foo.txt"         line 1
  2    "ls-output.txt"   line 0
Press ENTER or type command to continue		
%a表示当前显示的文件。
使用:buffer 2可以切换到指定的文件。

打开附加的文件编辑

也可以将文件添加到当前编辑的会话中,ex命令:e(edit的缩写)后跟一个文件名将打开另一个文件。比如:e ls-output.txt
然后就可以用:buffers命令查看当前打开的文件,用:buffer 2切换文件。

从一个文件复制内容到另一个文件

在编辑多个文件时,通常会希望将一个文件的一部分复制到另一个文件中。举例:
:buffer 1
yy
:buffer 2
p		

将整个文件插入到另一个文件

vi ls-output.txt
:r foo.txt		
:r命令(read的简写)将读取foo.txt文件的内容并将其插入到光标所在位置。

保存

保存文件最常用的ex命令是:w。在命令模式,ZZ将保存当前文件并退出vi,类似ex命令的:wq。
:w foo1.txt将文件另存为foo1.txt。需要注意的是,另存后继续编辑的文件还是foo.txt,而不是新的foo1.txt。