【PART 1】 简单编辑
#移动光标
h
j
k
l
+ 移动到下一行的行首,直接按回车也可以达到同样效果
- 移动到上一行的行首
一次移动几个位置,例:4l
#设置页面右边距 不是特别清楚这条命令的作用!
set wm=10 --将右边距设置为10
该命令不影响已经输入的行
还有许多set命令,以后介绍。
#行内移动
0 移动到行首
$ 移动到行尾
^ 移动到当前行的第一个非空格的字符
注意:^和0的区别,^把光标移动到当前行的第一个字符,并忽略任何空格或者制表符
0则把光标移动到当前行的第一个字符,而不管该位置是否为空格
( 移动到当前句子的开始 (往往以句号和问号等来作为一句的结束)
) 移动到下一句子的开始
{ 移动到当前段落的开始
} 移动到下一段落的开始
[[ 移动到当前节的开始
]] 移动到下一节的开始
-总结- 移动到行首可以有许多方法:
(a) 0
(b) ^
(c) ( 上一句的首部
(d) ) 下一句的首部
#按文本块移动
这里的文本块可以指“单词”,“句子”或者“段落”。
=向前=
w 每次光标向前移动一个单词,定位在单词的第一个字符
W 作用与w基本相同,只是它并不把标点和符号作为单词计算
=向后=
b 每次光标向后移动一个单词
B 作用与b基本相同,只是它并不把标点和符号作为单词计算
e或E 到下一个单词的尾部,e的大小写没有区别!
#按搜索移动
/pattern 向前搜索pattern模式
?pattern 向后搜索attern模式
n 同向重复搜索
N 反向重复搜索
eg.
d?move 删除从光标前到单词”move“之间所有文本(包括move本身)
d/move 删除从光标后到单词”move“之间所有文本(不包括move本身)
微型搜索:
fx 在行内搜索(移动光标到)x下一个实例,这里x代表任何字符
Fx 在行内搜索(移动光标到)x上一个实例
tx 在行内搜索(移动光标到)x下一个实例前面的字符
Tx 在行内搜索(移动光标到)x上一个实例后面的字符
; 同方向重复前面的搜索命令
, 反方向重复前面的搜索命令
带数字的w(W),b(B)命令
2w 光标向前移动2个单词
5B 光标向后不计标点移动5个单词
G:使用行号作为数字参数而直接移动到该行。这样做,比打:跟行号要简单!
不带行号,则把光标直接移动到文本的最后一行
CTRL G: 显示总行数及当前光标位置
=总结=
移动到指定行的方法
1. nG n为行号
2. :n (ex命令)
#插入文本
i 将文本插入光标之前
I 在行首插入文本
a 将文本插入光标之后
A 在行尾插入文本
o 在光标所在行的下面新建一行,等待输入文本
O 在光标所在行的上面新建一行,等待输入文本
插入命令的数字参数
通过数字前缀,可以使用i,I,a和A命令插入一排下划线或者替换字符。
eg.
输入50i*,然后按下两个ESC,将在光标所在位置前面插入50个*
输入25a*-, 然后按下两个ESC,将在光标所在位置后面插入25个"*-"
通过数字前缀,r可以使用一个单个字符的重复实例替换多个字符
#修改文本
cw 修改到单词尾部,其实它做的是删除光标所在位置到单词尾部所有字符,然后在原光标处等待用户输入
c2w 修改光标开始的两个单词
cb 修改到单词头
c2b 修改光标所在的前两个单词
c$ 修改到行尾 (大写的C有一样的效果)
c0(c^) 修改到行首
r 修改光标处的单个字符 (键入r,然后键入字母)
R 将插入模式变换成替换模式
我觉得R可以替换r命令
s 修改单个字符,它做的是删除光标所在字符,然后光标停留在下个字符上,并成为输入模式
r与s在实现功能上没有区别!
4s 修改4个字符,它做的是删除光标所在处后面的4个字符,然后光标停留在下个字符上,并成为输入模式
S 改变这个行,将删除整行,而不管光标当前的位置,注意它与C的不同!
=总结=
D 删除一整行,并保留空行;
dd 删除一整行,不保留空行;
S 删除一整行,不管光标位置在哪里,保留空行,并切换到编辑模式
C 删除光标右边该行所有内容,切换到编辑模式
大小写转换
~ 将光标所在位置的字母进行大小写转换
#删除文本
dw 删除光标定位在其首部的那个单词,注意单词后面的空格也被删除
dW 删除光标所在的单词,并且删除其后的标点符号
db 在光标位置向后删除一个单词
d$ 从光标位置删除到行尾
d0 从光标位置删除至行首
dd 删除整行
2dd 删除两行
D 删除光标所在行右边部分
x 删除光标所在位置的字符
5x 删除光标所在位置开始右边的5个字符
# 移动文本
在vi中,可以通过删除文本然后再把所删除的文本粘贴到文本中的文本位置来移动该文本。
p 把位于缓冲区中的文本粘贴到光标位置的后面
P 把位于缓冲区中的文本粘贴到光标位置的前面
xp:删除字符然后粘贴到字符后面,相当于将光标所在字符与之后的字符调换位置。
# 复制文本
yy 把光标所在行的文本复制到缓冲区中
yw 复制光标所在至单词尾复制到缓冲区中
yb 复制光标所在至单词头复制到缓冲区中
# 合并两行文本
J: 光标在第一行的任何位置,按下J,第二行将插入第一行的尾部
【PART 2】快速移动
# 滚动屏幕
^f: 向前滚动一屏
^b:向后滚动一屏
^d:向前滚动半屏
^u:向后滚动半屏
^e: 向下滚动一行 实际上光标是不动的
^y: 向上滚动一行
#使用z重新定位屏幕
z 再按下return: 把当前行移动到屏幕顶部并移动
z . : 把当前行移动到屏幕中央并移动
z - : 把当前行移动到屏幕底部并移动
#在屏幕内移动 (注意大写)
H 移动到起始点 - 屏幕首行
M 移动到屏幕的中间行
L 移动到屏幕的最后一行
=总结=
H,M,L与z,z.,z-的不同,前一组移动光标,不改变文本在屏幕中的位置;后一组改变光标所在行在屏幕中的位置。
nH 移动到屏幕首行下面的第n行
nL 移动到屏幕末行上面的第n行
另见【PART 1】按搜索移动
【PART 3】基本编辑命令的扩展
# 更多编辑命令
修改 删除 复制 从光标到………
cH dH yH 到屏幕顶端
cL dL yL 到屏幕底端
c+ d+ y+ 下一行,其实删除当前行和下一行
c5| d5| y5| 当前行的第5列
x
??????????????????????????????????????????????????????????????????????????????????????????
2c) dc) 2y( 接下来的第二个句子,当前行和下面两行
在Fedro中试验的结果是修改或删除到文本末,相当于"cG"
??????????????????????????????????????????????????????????????????????????????????????????
c{ d{ y{ 上一个段落
c/pattern d/pattern y/pattern 下一个pattern前
c?pattern d?pattern y?pattern 上一个pattern前
cn dn yn 下一个模式前
cG dG yG 文件尾部
c13G d13G y13G 第13行
#启动vi时的选项
A) 前进到指定的位置
$ vi +n file
打开文件到第n行
$ vi + file
打开文件到最后一行
$ vi +/pattern file
打开文件到模式首次出现的位置
B) 只读方式
$ vi -R file
或者
$ view file
# 利用缓冲区
* vi把前9次删除操作存储在编号缓冲区中,可以通过访问这些编号缓冲区中的任何一个来恢复前9次删除命令中的
任何一个(或全部)。最后一次删除将保存在1号缓冲区中,倒数第二次在2号缓冲区,依次类推。
* vi也允许把复制操作(复制文本)放置在字符标识的缓冲区中,可以用已复制的文本填满26个(a-z)缓冲区,
然后在编辑会话中的任何时刻使用粘贴那些文本。
# 恢复删除操作 【注意这种缓冲区的使用仅限于删除操作】
* 为了恢复删除操作,要输入”(双引号),并使用数字指定缓冲区中的文本,然后给出粘贴命令。
eg. "2p ~ 从2号缓冲区中恢复第二次删除的操作。
* 这里有个问题:如何查看各个缓冲区的内容?如何清空这些缓冲区?
* 如果无法确定所要恢复的删除操作存放在哪个缓冲区中,也不必反复输入"np。可以采用如下方法。
"1p.u.u.u. ……
这样就会依次把所有缓冲区中的内容粘贴到文件中。每输入一次u,恢复的文本就被删除;当输入圆点,下一个
缓冲区的内容就会恢复到文件中。一直输入u和.,直到恢复了在寻找的文本为止。
# 复制到命名缓冲区(a-z)
可以把y和d与26个命名缓冲区一起使用,这些缓冲区专门用于复制和删除文本。
方法是:使用双引号和表示想使用的缓冲区名字的字符
eg.
[1] "dyy 复制当前行到d缓冲区中
[2] "a7yy 复制接下来7行到a缓冲区中
[3] "dP 粘贴d缓冲区中的内容到光标前(注意这里所用的是大写P)
[4] "ap 粘贴a缓冲区中的内容到光标后
#书签
mx 用x(x可以为任何字符)标记当前位置
'x 移动光标到x所标记的行的首字符
?????????????????????????????????
`x 移动光标到x所标记的字符 ?
·· (两个反引号)返回到移动前的上一标记或上下文的确切位置
'' (两个引号)返回到上一标记或上下文所在行的开始
?????????????????????????????????
【PART 4】 ex编辑器
*ex的命令都以:开头。
#定义行的范围
eg.
[1] 3,18d 删除3~18行
[2] 160,224m23 移动160~224行到23行的下面
[3] 23,29co100 复制23~29行并把它们粘贴到100行的后面
显示行号 取消显示行号
: set nu :set nonu
=命令
[1] := 显示总行数
[2] :.= 显示当前行的行号
[3] :/pattern/= 显示第一个与模式相匹配的行的行号
# 行地址符
. 表示当前行
$ 表示文件的最后一行
% 表示文件中的每一行,相当于1,$的组合
eg.
=绝对寻址=
[1] :.,$d 删除从当前行到文件末尾之间的文本
[2] :20,.m$ 将从20行到当前的文本移动到文件的末尾
[3] :%d 删除文件所有行
[4] :%t$ 复制所有行并将它们粘贴到文件的末尾(成为连续的副本)
=相对寻址=
[1] :.,.+20d 删除从当前行开始向下的20行
[2] :226,$m.-2 将226行到文件末尾的文本移动到当前行上的两行
什么是当前行上的两行?
当前行号:23,文本将移动到22行开始的位置
[3] :.,+20# 显示从当前行下面20行的行号
如果在+和-的后面没有数字,它们就分别相当于+1和-1。
eg.
-,+t0 复制三行(从光标上面一行到光标下面一行),并把它们粘贴到文件的开头
# 搜索模式
:/pattern/d 删除下一个包含模式pattern的行
注意这个命令与d/while的区别!
:/pattern/+d 删除下一个包含模式pattern的行的下面的行
:/pattern1/,/pattern2/d 将从第一个包含模式pattern1的行到第一个包含模式pattern2的行之间的内容删除
:.,/pattern/m23 将从当前行到第一个包含模式pattern的行之间的文本移动到23行的后面
:/pattern/m$ 移动第一个包含pattern的行移动到文件的最后
:/pattern/;+10 p 显示下一个包含模式pattern的行和它下面的10行
# 全局搜索
:g/pattern 寻找文件中所有包含模式pattern的行
:g/pattern/p 作用与上一条命令相同
注意:在Fedro中,上面的两条命令的效果是一样的。但另一种说法是,第一条命令仅打印pattern在文件中
最后出现的位置。详见《学习VI编辑器》P.80
=总结=
/pattern/和g/pattern/的区别:前者以一个为单位一次寻找模式pattern在文件中的位置,继续寻找下一个时要按
ENTER键。后者,直接打印文件中所有包含模式pattern的行。
:g!/pattern/nu 寻找并显示文件中所有不包含模式pattern的行,同时还显示这些行的行号
:60,124g/pattern/p 寻找并显示第60行到124行之间所有包含模式pattern的行
# 组合ex命令
:1,3d | s/thier/their/ 把第一行到第三行删除;然后在当前行(该行是调用ex提示符以前的第四行)进行替换
:1,5m10 | g/pattern/nu 把第1行到第5行移动到第10行的后面,然后显示所有包含模式pattern的行和行号
# 保存和退出文件
[1] :w 把缓冲区写(保存)到文件但不退出
[2] :q 退出VI编辑器,如果之前对文件做了修改,是无法直接退出的
[3] :wq 写文件并退出编辑器,即使没有修改文件,写操作也会无条件的进行
[4] :x 写文件并退出编辑器,但只有修改了文件写操作才能进行
[5] :w! 可以把编辑保存到使用vi -R或view以只读方式打开的文件中(假设具有对该文件的写权限)
[6] :q! 允许在退出时不影响原来的文本,忽略在本次会话中进行的所有编辑,缓冲区中的内容将被删除。
退出时,另存文件
:w new_file (保存后,你所作的编辑依然是对旧文件)
保存部分文件
:230,$w newfile 将从第230行到文件末尾的文本保存到newfile中
.,600w newfile 将从当前行到第600行的文本保存到newfile中
添加到现有文件中
:340,$w >>newfile 将从第340行到文件末尾的文本添加到newfile中
# 把文件复制到另一个文件中
:r filename 把filename文件的内容插入到本文件中光标位置后面的行的开始
eg。
:r /home/tim/data 将要读取的文件放到光标位置后面的行
:&r /home/tim/data 将要读取的文件放到当前文件的尾部
:0r /home/tim/data 将要读取的文件放到当前文件的开头
:/pattern/r /home/tim/data 将要读取的文件放到当前文件中包含模式pattern的行的后面
# 在同一会话中,编辑多个文件
[1] 调用vi打开多个文件
vi file1 file2 ...
用ex命令:n调用下一个文件
[2] 使用参数列表
:arg 列出在命令行上指定的文件
:rew rewind, 把当前文件重新设置为命令行上指定的第一个文件
:last 把当前文件设置为命令行上指定的最后一个文件
[3] 调用新文件
可以使用:e引入一个新文件,此时正在编辑的文件称为“当前文件“(%),另一个文件称为”备用文件“(#)。
eg.
在编辑文件practice时,想要去编辑letter,可以输入:
:e letter
此时,practice是备用文件,而letter是当前文件。
想要返回practice,可以输入:
:e #
另一种情况,想要放弃所有在letter中做的编辑而返回practice:
:e! #
也可以将备用文件的内容拷贝到当前文件中:
:r # 将备用文件中
将当前文件另存为文件new:
:w %.new
=总结=
其实无论在编辑文件时使用:e,还是直接在参数中指定多个文件,都可以使用#,%,以及r等命令来进行文件之间的拷贝。
[4] CTRL ^: 切换文件
# 利用缓冲去在文件之间进行编辑的例子
example 1
[1] 在文件pratice中使用拷贝内容
"f3yy 拷贝从光标所在行开始的三行到缓冲区f中
[2] 切换到letter文件
:e letter
[3] 在letter文件中放置复制的文件内容
"fp 粘贴缓冲区f的内容到光标的下面一行
example 2
[1] 将当前文件的第165行到226行拷贝到缓冲区a中
:165,226ya a
[2] 打开一个新的文件
:e newfile
[3] 粘贴到新文件当前行的后面
:pu a
【PART 5】 高级编辑
# 定制VI
~ VI有许多可以在其内部进行设置的选项。这些设置影响它的操作方式。可以在VI中使用ex的:set命令修改这些选项。
~ 无论VI什么时候启动,它都要读取主目录下的.exrc文件以获取进一步的操作指令。通过在该文件中放置:set命令,
就可以使用VI的任何时候改变它的操作方式。也可以在本地目录下建立.exrc文件来初始化需要在不同环境中使用的
各个选项。
~ 最后,存储在shell变量EXINIT中的任何命令都将在VI启动时执行,EXINIT中的设置将覆盖主目录.exrc文件中的设置。
# set命令
set命令用来社字汇VI的各种选项。有两种类型的选项可以使用:set命令修改。
- 非开即关的触发选项
- 带数字或字符串值的选项
触发选项
:set option 开启选项
:set nooption 关闭选项
eg.
:set ic 指定模式搜索忽略大小写
:set noic
设置值的选项
eg.
:set window=20 设置屏幕窗口上所显示的行数
查看VI所使用的选项
[1] :set all 查看所有选项
[2] :set option? 查看单个选项option的当前值
[3] :set 查看在.exrc文件或当前会话其间明确修改或设置过的选项
# .exrc文件
控制VI环境的.exrc文件位于主目录下(首次登录时所在的目录)。可以用VI编辑器修改.exrc文件。
eg. 简单的.exrc文件
set nowrapscan wrapmargin=7 --设置页边距wrapmargin
set section=SeAhBhChDh nomesg
map q :w^M:n^M
map v dwElp
ab ORA O'Relly & Associates, inc.
# 替换环境
除了读取主目录下的.exrc文件之外,有其他方法来设置VI的环境。
[1] 使VI读取当前目录下名为.exrc的文件;
所有VI的现有版本中,在VI读取当前目录下的.exrc文件之前,必须先在主目录下的.exrc文件中设置exrc选项:
set exec
[2] 把选项设置保存到不同于.exrc文件的文件中,然后使用:so命令读取该文件来定义另外的VI环境。
eg. :so .progoptions
# 有用的选项
autowrite选项 对其设置后,vi在调用:n(next)命令移动到下个文件进行编辑时和使用:!运行shell命令之前
将自动写出已修改的缓冲区内容。
# 执行shell命令
[1] 执行单个命令的方法::!command
[2] 执行多个命令且期间不想退回VI::sh
返回VI需要输入CTRL D
[3] 把UNIX命令的执行结果读入文件中,可使用:read
eg.
:0r !date 在文件的第一行插入系统时间
:r !sort phone 在文本末尾插入对文件phone排序的结果
:1,10!sort 使用sort对第1行到第10行进行过滤,并用其输出取代这些行
[4] 使用VI过滤文本
在VI中,通过依次输入感叹号、任何指示文本块的VI移动键(G,{,},(,),[[,]],+,-)和所要执行的UNIX命令,
即可使用该UNIX命令对文本进行过滤。
eg.
a) 把光标所在行的字母都变为大写
!!tr '[a-z]' '[A-Z]'
b) 将当前段落的字母变成大写
!)tr '[a-z]' '[A-Z]'
c) 将当前行至第5行的字母变成大写
!13Gtr '[a-z]' '[A-Z]'
# 保存命令
[1] ex命令定义单词缩写
格式 :ab abbr phrase
作用 将abbr定义为phrase的缩写
取消缩写
格式 :unab abbr
作用 取消abbr缩写
列出当前定义的缩写
格式 :ab
[2] 使用映射命令 - 使用map将一个命令序列映射为一个不使用的键
:map x sequence 把字符x定义为一系列编辑命令
:unmap x 取消为x定义的序列
:map 列出当前映射的所有字符
可以用作映射用户定制的命令序列的字符:
字母
g K q V v
控制键
^A ^K ^O ^W ^X
符号
_ * / =
在定义映射时,不能只输入RETURN、ESC、BACKSPACE和DELETE之类的键作为映射命令的一部分,因为这些键已在ex内有
含义了。如果想在命令序列中包含这些键的某一个,则必须在该键之前使用CTRL-V来避开它的正常含义。
另外注意,有三个控制键也需要使用CTRL-V进行转义:^T,^W和^X。
一些映射的举例
:map e ea 移动到单词尾部并添加文本
:map K dwElp 调换两个单词
:map g I/*[A*/^[ 将C/C++的注释符号放在该行两端