屏幕文本编辑器Vi
本章介绍Linux上最常用的文本编辑器Vi。文本编辑器是所有计算机系统中最常使用的一种工具。用户在使用计算机的时候,往往需要建立自己的文件,无论是一般的文本文件、数据文件,还是编写的源程序文件,这些工作都离不开编辑器。
Linux系统提供了一个完整的编辑器家族系列,如Ed、Ex、Vi和Emacs等,按功能它们可以分为两大类:行编辑器(Ed、Ex)和全屏幕编辑器
(Vi、Emacs)。行编辑器每次只能对一行进行操作,使用起来很不方便。而全屏幕编辑器可以对整个屏幕进行编辑,用户编辑的文件直接显示在屏幕上,修
改的结果可以立即看出来,克服了行编辑的那种不直观的操作方式,便于用户学习和使用,具有强大的功能。
Vi是Linux系统的第一个全屏幕交互式编辑程序,它从诞生至今一直得到广大用户的青睐,历经数十年仍然是人们主要使用的文本编辑工具,足见其生命力之强,而强大的生命力是其强大的功能带来的。
本章中,我们将循序渐进地介绍如何使用Vi来建立、编辑、显示以及处理文件。(注:文中的大写字母为[shift]键+相应的小写字母的组合)
Vi简介
Vi是“Visual interface”的简称,它在Linux上的地位就仿佛Edit程序在DOS上一样。它可以执行输出、删除、查找、替换、块操作等众多文本操作,而且用户可以根据自己的需要对其进行定制,这是其他编辑程序所没有的。
Vi不是一个排版程序,它不象Word或WPS那样可以对字体、格式、段落等其他属性进行编排,它只是一个文本编辑程序。
Vi没有菜单,只有命令,且命令繁多。Vi有三种基本工作模式:命令行模式、文本输入模式和末行模式。
命令行模式
任何时候,不管用户处于何种模式,只要按一下键,即可使Vi进入命令行模式;我们在shell环境(提示符为$)下输入启动Vi命令,进入编辑器时,也是处于该模式下。
在该模式下,用户可以输入各种合法的Vi命令,用于管理自己的文档。此时从键盘上输入的任何字符都被当做编辑命令来解释,若输入的字符是合法的Vi命令,
则Vi在接受用户命令之后完成相应的动作。但需注意的是,所输入的命令并不在屏幕上显示出来。若输入的字符不是Vi的合法命令,Vi会响铃报警。
文本输入模式
在命令模式下输入插入命令i、附加命令a 、打开命令o、修改命令c、取代命令r或替换命令s都可以进入文本输入模式。在该模式下,用户输入的任何字符都被Vi当做文件内容保存起来,并将其显示在屏幕上。在文本输入过程中,若想回到命令模式下,按键即可。
末行模式
末行模式也称ex转义模式。
Vi和Ex编辑器的功能是相同的,二者主要区别是用户界面。在Vi中,命令通常是单个键,例如i、a、o等;而在Ex中,命令是以按回车键结束的正文行。
Vi有一个专门的“转义”命令,可访问很多面向行的Ex命令。在命令模式下,用户按“:”键即可进入末行模式下,此时Vi会在显示窗口的最后一行(通常也
是屏幕的最后一行)显示一个“:”作为末行模式的提示符,等待用户输入命令。多数文件管理命令都是在此模式下执行的(如把编辑缓冲区的内容写到文件中
等)。末行命令执行完后,Vi自动回到命令模式。例如:
:1,$s / A / a / g
则从文件第一行至文件尾将大写A全部替换成小写a。
若在末行模式下输入命令过程中改变了主意,可按键,或用退格键将输入的命令全部删除之后,再按一下退格键,即可使Vi回到命令模式下。
Vi编辑器的三种工作模式之间的转换如图11-1所示。
如果要从命令模式转换到编辑模式,可以键入命令a或者i;如果需要从文本模式返回,则按Esc键即可。在命令模式下输入“:”即可切换到末行模式,然后输入命令。
第二十五课 Vi的进入与退出 2000年/6月/13日
Vi 的进入
用户登录到系统中之后,系统给出提示符“$”。在提示符后键入Vi和想要编辑(或建立)的文件名,便可进入Vi。
[例1] 键入命令:
$ vi example.c
屏幕显示如下:
~
~
~
~
~
~
~
~
~
~
~
~
~
“ example.c” [New File]
如果只键入Vi,而不带文件名,也可以进入Vi。之后在光标处键入文件内容,退出Vi时,只需在退出命令后输入文件名即可。
进入Vi之后,首先进入的就是命令模式,也就是说等待命令输入而不是文本输入。这时输入的字母都将作为命令来解释。光标停在屏幕第一行首位上(用表示),
其余各行行首均有一个“~”符号,表示该行为空行。最后一行也称状态行,显示出当前正在编辑的文件名以及其状态。如本例是[New
File],表示example.c是一个新建的文件。如果example.c文件已在系统中存在,那么输入上述命令后,则在屏幕上显示出该文件的内容,
并且光标停在第一行的首位,在状态行显示出该文件的文件名、行数和字符数。
[例2] 键入命令:
$ vi example.c
然后键入:
#include
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
“ example.c” [ New File]
注意,在这里我们为了节省篇幅起见,屏幕只显示15行。事实上,初始的显示行数与用户所用终端有关,一般的CRT终端可显示25行。在窗口系统中,显示行
数与运行Vi的那个窗口有关。然而我们可以对显示行数进行设置。例如,在能显示25行的CRT终端上,让Vi只显示15行。设置的方法将在本节后面介绍。
当用Vi建立一个新文件时,在进入Vi的命令中也可以不给出文件名,当编辑完文件需要保存数据时,再由用户指定文件名。
进入Vi时,用户不仅可以指定一个待编辑的文件名,而且还有许多附加操作。
如果希望在进入Vi之后,光标处于文件中特定的某行上,可在Vi后加上任选项+n,其中n为指定的行数。
[例3] 键入命令:
$ vi +5 example1.c
后,屏幕显示如下:
#include
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
~
“ example.c” 12 lines, 125 characters
光标将位于文件example1.c中的第5行上。
如果希望在进入Vi之后光标处于文件最末行,则只需把命令中附加项“+”后面的数字n省略掉即可。
在进入Vi时,除了可以指定一个光标起始行号之外,还可以在命令中指定一个模式串,此时在进入Vi后,光标就处于文件中第一个与指定模式串相匹配的那行上。
[例4] 键入命令:
$ vi +/int example1.c
屏幕显示如下:
#include
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
~
“ example.c” 12 lines, 125 characters
光标将位于文件example1.c中的第3行上。
使用Vi可以同时编辑多个文件,只要在进入Vi的命令中写入所要操作的文件即可,还可以使用通配符。
[例5] 键入命令:
$ vi *.cat
就可以编辑所有后缀为cat的文件了。当然,您还可以使用shell中内置的模式匹配来装载文件,这样会更富技巧性。一旦您在命令行中包含了所有的待编辑文件名,就可以在Vi中方便地移来移去。
退出Vi
当编辑完文件,准备退出Vi返回到shell时,可以使用以下几种方法之一。
在命令模式中,连按两次大写字母Z,若当前编辑的文件曾被修改过,则Vi保存该文件后退出,返回到shell;若当前编辑的文件没被修改过,则Vi直接退出, 返回到shell。
在末行模式下,输入命令
:w
Vi保存当前编辑文件,但并不退出,而是继续等待用户输入命令。在使用w命令时,可以再给编辑文件起一个新的文件名。
[例6]
:w newfile
此时Vi将把当前文件的内容保存到指定的newfile中,而原有文件保持不变。若newfile是一个已存在的文件,则Vi在显示窗口的状态行给出提示信息:
File exists (use ! to override)
此时,若用户真的希望用文件的当前内容替换newfile中原有内容,可使用命令
:w! newfile
否则可选择另外的文件名来保存当前文件。
在末行模式下,输入命令
:q
系统退出Vi返回到shell。若在用此命令退出Vi时,编辑文件没有被保存,则Vi在显示窗口的最末行显示如下信息:
No write since last change (use ! to overrides)
提示用户该文件被修改后没有保存,然后Vi并不退出,继续等待用户命令。若用户就是不想保存被修改后的文件而要强行退出Vi时,可使用命令
:q!
Vi放弃所作修改而直接退到shell下。
在末行模式下,输入命令
:wq
Vi将先保存文件,然后退出Vi返回到shell。
在末行模式下,输入命令
:x
该命令的功能同命令模式下的ZZ命令功能相同。
Vi中的行号
Vi中的许多命令都要用到行号及行数等数值。若编辑的文件较大时,自己去数是非常不方便的。为此Vi提供了给文本加行号的功能。这些行号显示在屏幕的左边,而相应行的内容则显示在行号之后。
使用的命令为:在末行方式下输入命令:
:set number
需要说明的是,这里加的行号只是显示给用户看的,它们并不是文件内容的一部分。
在一个较大的文件中,用户可能需要了解光标当前行是哪一行,在文件中处于什么位置,可在命令模式下用组合键<Ctrl+g>,此时Vi会在显示窗口的最后一行显示出相应信息。该命令可以在任何时候使用。
[例7]
#include <stdio.h>
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
~
“ example.c” [Modified] lines 4 of 10 --40%-- col 11
在末行方式下,我们可以输入命令nu(单词number的缩写)来获得光标当前行的行号与该行内容。
光标移动操作
全屏幕文本编辑器中,光标的移动操作无疑是最经常使用的操作了。用户只有熟练地使用移动光标的这些命令,才能迅速准确地到达所期望的位置处进行编辑。
Vi中的光标移动既可以在命令模式下,也可以在文本输入模式下,但操作的方法不尽相同。
在文本输入模式下,可直接使用键盘上的四个方向键移动光标。
在命令模式下,有很多移动光标的方法。不但可以使用四个方向键来移动光标,还可以用h、j、k、l这四个键代替四个方向键来移动光标,这样可以避免由于不
同机器上的不同键盘定义所带来的矛盾,而且使用熟练后可以手不离开字母键盘位置就能完成所有操作,从而提高工作效率。另外还可以用<
Spacebar>、<Backspace>、<Ctrl+n>和<ctrl+p>四个键或组合键移动光标。
且以上这三种键在实现功能上是等价的。除此之外,还有一些移动光标的命令。下面对它们的工作方式介绍如下:
<Spacebar>、® (均称为右向键)
右向键的作用是将光标向右移动一个位置。若在向右键前先输入一个数字n,那么光标就向右移动n个位置。例如5l表示光标向右移动5个位置。需要注意的是,
光标移动不能超过当前行的末尾。若给定的n超过光标当前位置至行尾的字符个数,如果用右向键,光标只能移到行尾;如果用<
Spacebar>,光标移到下面一行或几行的适当位置。
h、<Backspace>、¬ (向左键)
执行一次向左键,光标向左移动一个位置。同向右键一样,也可以在向左键的前面输入一个数字n,那么光标就向左移动n个位置。需要注意的是,如果用左向键,光标左移不能超出该行的开头;如果用<Backspace>,光标移到上面一行或几行的适当位置。
j、<Ctrl+n>、¯ (向下键)
执行一次向下键光标向下移动一个位置(即一行),但光标所在的列不变。当这些命令前面加上数字n,则光标下移n行。
Vi除了可以用向下键将光标下移外,还可以用<Enter>键和“+”键将光标下移一行或n行(不包括本行在内),但此时光标下移之后将位于该行的第一个字符处。例如:
3j 光标下移3行,且光标所在列的位置不变。
3+或3<Enter> 光标下移3行,且光标位于该行的行首。
k、<Ctrl+p>、 (向上键)
执行一次向上键光标向上移动一个位置(即一行),但光标所在的列不变。同样在这些命令前面加上数字n,则光标上移n行。
若希望光标上移之后,光标位于该行的行首,则可以使用命令“- ”。
L (移至行首)
L 命令是将光标移到当前行的开头,即将光标移至当前行的第一个非空白处(非制表符或非空格符)。
$(移至行尾)
该命令将光标移到当前行的行尾,停在最后一个字符上。若在$命令之前加上一个数字n,则光标下移n-1行并到达行尾。
[行号] G(移至指定行)
该命令将光标移至指定行号所指定的行的行首。这种移动称为绝对定位移动。
[例8]
#include <stdio.h>
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
~
“ example.c” 12 lines, 125 characters
键入命令:6G后,屏幕显示如下:
#include <stdio.h>
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( );
}
add( )
{ static int x=0;
x++ ;
printf(“x = %d\n”, x);
}
~
~
~
~
~
“ example.c” 12 lines, 125 characters
光标移到了第6行的行首。
若省略行号,则光标移至该文件的最后一行的行首,即无论该文件有多少屏,都跳至最后一行。
第二十七课 vi命令 2000年/6月/26日
在屏幕上移动
Vi提供了三个关于光标在全屏幕上移动并且文件本身不发生滚动的命令。它们分别是H、M和L命令。
1. H命令
该命令将光标移至屏幕首行的行首(即左上角),也就是当前屏幕的第一行,而不是整个文件的第一行。利用此命令可以快速将光标移至屏幕顶部。若在H命令之前加上数字n,则将光标移至第n行的行首。
[例9] 屏幕显示如下内容:
#include <stdio.h>
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( ); }
add( )
{ static int x=0;
x++ ;
printf(“x=%d\n”, x);
}
~
~
~
~
~
“ example.c” [ New File]
在命令模式下输入4H命令后,光标移到以for开头的这一行的字母f上。
值得一提的是,使用命令dH将会删除从光标当前所在行至所显示屏幕首行的全部内容。
2. M命令
该命令将光标移至屏幕显示文件的中间行的行首。即如果当前屏幕已经充满,则移动到整个屏幕的中间行;如果并未充满,则移动到文本的那些行的中间行。利用此
命令可以快速地将光标从屏幕的任意位置移至屏幕显示文件的中间行的行首。例如,在上面屏幕显示的情况下(不论光标在屏幕的何处),在命令模式下,输入命令
M之后,光标都将移到add这一行的字母a上。
同样值得一提的是,使用命令dM将会删除从光标当前所在行至屏幕显示文件的中间行的全部内容。
3. L命令
当文件显示内容超过一屏时,该命令将光标移至屏幕上的最底行的行首;当文件显示内容不足一屏时,该命令将光标移至文件的最后一行的行首。可见,利用此命令
可以快速准确地将光标移至屏幕底部或文件的最后一行。若在L命令之前加上数字n,则将光标移至从屏幕底部算起第n行的行首。例如,在上面屏幕显示的情况下
(不论光标在屏幕的何处),在命令模式下,输入命令3L之后,光标都将移到x++这一行的字母x上。
同样值得一提的是,使用命令dL将会删除从光标当前行至屏幕底行的全部内容。
按字移动光标
首先介绍一下Vi中“字”的概念。在Vi中“字”有两种含义。一种是广义的字,它可以是两个空格之间的任何内容。
[例10] 在文件example.c 中的第4行:
{int k;
它只有2个字,一个是{int ,另一个是k;
Vi中另一种字是狭义上的字,在此种意义之下,英文单词、标点符号和非字母字符(如!、@、#、$、%、^、&、*、(、)、-、+、{、}、
[、]、~、|、\、<、>、/等)均被当成是一个字。因此,上面那一行中就包括{、int、k、;这4个字。
Vi中使用大写命令一般就是指将字作为广义来对待,使用小写命令就是作为狭义对待。
搞清楚Vi中字的含义后,我们就可以介绍按字移动光标的命令了。
Vi 一共提供了三组关于按字移动光标的命令,分别是:
1. w和W命令
将光标右移至下一个字的字首;
[例11] 屏幕上显示如下:
printf(“Hello Mr.Huang!\n”);
现在使用w命令,把光标移到下一个字(狭义)的字首“(”上:
printf(“Hello Mr.Huang!\n”);
下面使用W命令,将把光标移到下一个字(广义)的字首“M”上:
printf(“Hello Mr.Huang!\n”);
2. e和E命令
如果光标起始位置处于字内(即非字尾处),则该命令将把光标移到本字字尾;如果光标起始位置处于字尾,则该命令将把光标移动到下一个字的字尾。
3. b和B
如果光标处于所在字内(即非字首),则该命令将把光标移至本字字首;如果光标处于所在字字首,则该命令将把光标移到上一个字的字首。
[例12] 屏幕显示如下:
printf(“Hello Mr.Huang!\n”);
现在使用b命令,由于光标处于该字中间,所以光标移动到本字字首“H”处:
printf(“Hello Mr.Huang!\n”);
如果使用B命令,则如下所示:
printf(“Hello Mr.Huang!\n”);
按句移动光标
在Vi中,一个句子被定义为是以逗号(,)、句号(.)、问号(?)和感叹号(!)结尾,且其后面跟着至少两个以上(含两个)空格或一个换行符的字符序列。
Vi提供了关于按句移动光标的两个命令,分别为:
1. ( 命令
将光标移至上一个句子的开头。
2. ) 命令
该命令将光标移至下一个句子的开头。
按段移动光标
在Vi中,一个段被定义为是以一个空白行开始和结束的片段。Vi提供了关于按段移动光标的两个命令,分别为:
1. { 命令
该命令将光标向前移至上一个段的开头;
2. } 命令
该命令将光标向后移至下一个段的开头。
屏幕滚动
屏幕命令是以屏幕为单位移动光标的,常用于文件的滚屏和分页。需要注意的是,屏幕命令不是光标移动命令,不能作为文本限定符用于删除命令中。
在命令模式下和文本输入模式下均可以使用屏幕滚动命令。
1. 滚屏命令
关于滚屏命令有两个:
· < Ctrl+u > 将屏幕向前(文件头方向)翻滚半屏;
· < Ctrl+d > 将屏幕向后(文件尾方向)翻滚半屏。
可以在这两个命令之前加上一个数字n,则屏幕向前或向后翻滚n行。并且这个值被系统记住,以后再用< Ctrl+u >和< Ctrl+d >命令滚屏时,还滚相应的行数。
2. 分页命令
关于分页命令也有两个:
· < Ctrl+f > 将屏幕向文件尾方向翻滚一整屏(即一页);
· < Ctrl+b > 将屏幕向文件首方向翻滚一整屏(即一页)。
同样也可以在这两个命令之前加上一个数字n,则屏幕向前或向后移动n页。
3. 状态命令< Ctrl+G >
命令显示在vi状态行上的vi状态信息,包括正在编辑的文件名、是否修改过、当前行号、文件的行数以及光标之前的行占整个文件的百分比。
4. 屏幕调零命令
Vi 提供了三个有关屏幕调零的命令。它们的格式分别为:
· [行号] z [行数] <回车>
· [行号] z [行数] .
· [行号] z [行数] _
若省略了行号和行数,这三个命令分别为将光标所在的当前行作为屏幕的首行、中间行和最末行重新显示;若给出行号,那么该行号所对应的行就作为当前行显示在屏幕的首行、中间行和最末行;若给出行数,则它规定了在屏幕上显示的行数。
[例13]
8z16<回车> :将文件中的第8行作为屏幕显示的首行,并一共显示16行。
15z . :将文件中的第15行作为屏幕显示的中间行,显示行数为整屏。
15z 5_ :将文件中的第15行作为屏幕显示的最末行,显示行数为5行。
文本插入操作
在命令模式下用户输入的任何字符都被Vi当作命令加以解释执行,如果用户要将输入的字符当作是文本内容时,则首先应将Vi的工作模式从命令模式切换到文本输入模式。切换的方式是使用下面的命令。
插入(Insert)命令
Vi提供了两个插入命令:i和 I。
1. i命令
插入文本从光标所在位置前开始,并且插入过程中可以使用<Backspace>键删除错误的输入。此时Vi处于插入状态,屏幕最下行显示“--INSERT--”(插入)字样。
[例14] 有一正在编辑的文件,如下所示:
Welcome to vi world!Come on!
~
~
光标位于第一个“!”上,需在其前面插入:
This is an example!
使用i命令,并输入相应文本后,屏幕显示如下:
Welcome to vi world This is an example!!Come on!
~
~
由此例可以看到,光标本来是在第一个“!”处,但是由于是从光标所在位置前开始插入,所以这个“!”就被挤到了新插入的文本之后。
2. I命令
该命令是将光标移到当前行的行首,然后在其前插入文本。
vi命令
在屏幕上移动
Vi提供了三个关于光标在全屏幕上移动并且文件本身不发生滚动的命令。它们分别是H、M和L命令。
1. H命令
该命令将光标移至屏幕首行的行首(即左上角),也就是当前屏幕的第一行,而不是整个文件的第一行。利用此命令可以快速将光标移至屏幕顶部。若在H命令之前加上数字n,则将光标移至第n行的行首。
[例9] 屏幕显示如下内容:
#include <stdio.h>
main ( )
{ int k ;
for ( k=0 ; k<3 ; k++) add( ); }
add( )
{ static int x=0;
x++ ;
printf(“x=%d\n”, x);
}
~
~
~
~
~
“ example.c” [ New File]
在命令模式下输入4H命令后,光标移到以for开头的这一行的字母f上。
值得一提的是,使用命令dH将会删除从光标当前所在行至所显示屏幕首行的全部内容。
2. M命令
该命令将光标移至屏幕显示文件的中间行的行首。即如果当前屏幕已经充满,则移动到整个屏幕的中间行;如果并未充满,则移动到文本的那些行的中间行。利用此
命令可以快速地将光标从屏幕的任意位置移至屏幕显示文件的中间行的行首。例如,在上面屏幕显示的情况下(不论光标在屏幕的何处),在命令模式下,输入命令
M之后,光标都将移到add这一行的字母a上。
同样值得一提的是,使用命令dM将会删除从光标当前所在行至屏幕显示文件的中间行的全部内容。
3. L命令
当文件显示内容超过一屏时,该命令将光标移至屏幕上的最底行的行首;当文件显示内容不足一屏时,该命令将光标移至文件的最后一行的行首。可见,利用此命令
可以快速准确地将光标移至屏幕底部或文件的最后一行。若在L命令之前加上数字n,则将光标移至从屏幕底部算起第n行的行首。例如,在上面屏幕显示的情况下
(不论光标在屏幕的何处),在命令模式下,输入命令3L之后,光标都将移到x++这一行的字母x上。
同样值得一提的是,使用命令dL将会删除从光标当前行至屏幕底行的全部内容。
按字移动光标
首先介绍一下Vi中“字”的概念。在Vi中“字”有两种含义。一种是广义的字,它可以是两个空格之间的任何内容。
[例10] 在文件example.c 中的第4行:
{int k;
它只有2个字,一个是{int ,另一个是k;
Vi中另一种字是狭义上的字,在此种意义之下,英文单词、标点符号和非字母字符(如!、@、#、$、%、^、&、*、(、)、-、+、{、}、
[、]、~、|、\、<、>、/等)均被当成是一个字。因此,上面那一行中就包括{、int、k、;这4个字。
Vi中使用大写命令一般就是指将字作为广义来对待,使用小写命令就是作为狭义对待。
搞清楚Vi中字的含义后,我们就可以介绍按字移动光标的命令了。
Vi 一共提供了三组关于按字移动光标的命令,分别是:
1. w和W命令
将光标右移至下一个字的字首;
[例11] 屏幕上显示如下:
printf(“Hello Mr.Huang!\n”);
现在使用w命令,把光标移到下一个字(狭义)的字首“(”上:
printf(“Hello Mr.Huang!\n”);
下面使用W命令,将把光标移到下一个字(广义)的字首“M”上:
printf(“Hello Mr.Huang!\n”);
2. e和E命令
如果光标起始位置处于字内(即非字尾处),则该命令将把光标移到本字字尾;如果光标起始位置处于字尾,则该命令将把光标移动到下一个字的字尾。
3. b和B
如果光标处于所在字内(即非字首),则该命令将把光标移至本字字首;如果光标处于所在字字首,则该命令将把光标移到上一个字的字首。
[例12] 屏幕显示如下:
printf(“Hello Mr.Huang!\n”);
现在使用b命令,由于光标处于该字中间,所以光标移动到本字字首“H”处:
printf(“Hello Mr.Huang!\n”);
如果使用B命令,则如下所示:
printf(“Hello Mr.Huang!\n”);
按句移动光标
在Vi中,一个句子被定义为是以逗号(,)、句号(.)、问号(?)和感叹号(!)结尾,且其后面跟着至少两个以上(含两个)空格或一个换行符的字符序列。
Vi提供了关于按句移动光标的两个命令,分别为:
1. ( 命令
将光标移至上一个句子的开头。
2. ) 命令
该命令将光标移至下一个句子的开头。
按段移动光标
在Vi中,一个段被定义为是以一个空白行开始和结束的片段。Vi提供了关于按段移动光标的两个命令,分别为:
1. { 命令
该命令将光标向前移至上一个段的开头;
2. } 命令
该命令将光标向后移至下一个段的开头。
屏幕滚动
屏幕命令是以屏幕为单位移动光标的,常用于文件的滚屏和分页。需要注意的是,屏幕命令不是光标移动命令,不能作为文本限定符用于删除命令中。
在命令模式下和文本输入模式下均可以使用屏幕滚动命令。
1. 滚屏命令
关于滚屏命令有两个:
· < Ctrl+u > 将屏幕向前(文件头方向)翻滚半屏;
· < Ctrl+d > 将屏幕向后(文件尾方向)翻滚半屏。
可以在这两个命令之前加上一个数字n,则屏幕向前或向后翻滚n行。并且这个值被系统记住,以后再用< Ctrl+u >和< Ctrl+d >命令滚屏时,还滚相应的行数。
2. 分页命令
关于分页命令也有两个:
· < Ctrl+f > 将屏幕向文件尾方向翻滚一整屏(即一页);
· < Ctrl+b > 将屏幕向文件首方向翻滚一整屏(即一页)。
同样也可以在这两个命令之前加上一个数字n,则屏幕向前或向后移动n页。
3. 状态命令< Ctrl+G >
命令显示在vi状态行上的vi状态信息,包括正在编辑的文件名、是否修改过、当前行号、文件的行数以及光标之前的行占整个文件的百分比。
4. 屏幕调零命令
Vi 提供了三个有关屏幕调零的命令。它们的格式分别为:
· [行号] z [行数] <回车>
· [行号] z [行数] .
· [行号] z [行数] _
若省略了行号和行数,这三个命令分别为将光标所在的当前行作为屏幕的首行、中间行和最末行重新显示;若给出行号,那么该行号所对应的行就作为当前行显示在屏幕的首行、中间行和最末行;若给出行数,则它规定了在屏幕上显示的行数。
[例13]
8z16<回车> :将文件中的第8行作为屏幕显示的首行,并一共显示16行。
15z . :将文件中的第15行作为屏幕显示的中间行,显示行数为整屏。
15z 5_ :将文件中的第15行作为屏幕显示的最末行,显示行数为5行。
文本插入操作
在命令模式下用户输入的任何字符都被Vi当作命令加以解释执行,如果用户要将输入的字符当作是文本内容时,则首先应将Vi的工作模式从命令模式切换到文本输入模式。切换的方式是使用下面的命令。
插入(Insert)命令
Vi提供了两个插入命令:i和 I。
1. i命令
插入文本从光标所在位置前开始,并且插入过程中可以使用<Backspace>键删除错误的输入。此时Vi处于插入状态,屏幕最下行显示“--INSERT--”(插入)字样。
[例14] 有一正在编辑的文件,如下所示:
Welcome to vi world!Come on!
~
~
光标位于第一个“!”上,需在其前面插入:
This is an example!
使用i命令,并输入相应文本后,屏幕显示如下:
Welcome to vi world This is an example!!Come on!
~
~
由此例可以看到,光标本来是在第一个“!”处,但是由于是从光标所在位置前开始插入,所以这个“!”就被挤到了新插入的文本之后。
2. I命令
该命令是将光标移到当前行的行首,然后在其前插入文本。
}
第二十九课 vi命令 2000年/7月/10日
附加(append)命令
Vi提供了两个附加插入命令:a和A。
1. a命令
该命令用于在光标当前所在位置之后追加新文本。新输入的文本放在光标之后,在光标后的原文本将相应地向后移动。光标可在一行的任何位置。
[例15] 以例14原始情况为例,使用a命令,并输入相应文本,屏幕显示如下:
Welcome to vi world!This is an example!Come on!
~
~
本例中光标后的文本“Come on!”被新输入的文本挤到了后面。
2. A命令
该命令与a命令不同的是,A命令将把光标挪到所在行的行尾,从那里开始插入新文本。当输入A命令后,光标自动移到该行的行尾。
a和A命令是把文本插入到行尾的唯一方法。
打开(open)命令
不论是Insert命令也好,还是append命令也好,所插入的内容都是从当前行中的某个位置开始的。若我们希望在某行之前或某行之后插入一些新行,则应使用open命令。
Vi提供了两个打开命令:o和O。
1. o命令
该命令将在光标所在行的下面新开一行,并将光标置于该行的行首,等待输入文本。要注意,当使用<Backspace>删除字符时只能删除从插
入模式开始的位置以后的字符,对于以前的字符不起作用。而且还可以在文本输入方式下输入一些控制字符,例如,Ctrl+l即是插入分页符,显示为^L。
[例16] 以例14的原始情况为例,只是这次要在当前行下面一行输入文本。使用o命令,并输入相应文本,屏幕显示如下:
Welcome to vi world!Come on!
This is an example!
~
~
新输入的文本出现在原来文本所在行的下一行。
2. O命令
和o命令相反,O命令是在光标所在行的上面插入一行,并将光标置于该行的行首,等待输入文本。
[例17] 与例14的原始情况相同,要在当前行的上面一行输入文本。使用O命令并输入文本后,屏幕显示如下:
This is an example!
Welcome to vi world!Come on!
~
~
文本插入到了当前行之上。
11.3.4 文本修改
在命令模式下可以使用Vi提供的各种有关命令对文本进行修改,包括对文本内容的删除、复制、取代和替换等。
文本删除
在编辑文本时,经常需要删除一些不需要的文本,我们可以用<Backspace>键将输错或不需要的文本删除,但此时有一个限制就是当删到行头之后,再想删上面那行的内容是不可能的。
在命令模式下,Vi提供了许多删除命令。这些命令大多是以d开头的。常用的有:
1. 删除单个字符
x: 删除光标处的字符。若在x之前加上一个数字n,则删除从光标所在位置开始向右的n个字符。
X:删除光标前面的那个字符。若在X之前加上一个数字n,则删除从光标前面那个字符开始向左的n个字符。
显然这两个命令是删除少量字符的快捷方法。
2. 删除多个字符
dd:删除光标所在的整行。在dd前可加上一个数字n,表示删除当前行及其后n-1行的内容。
D或d$:两命令功能一样,都是删除从光标所在处开始到行尾的内容。
d0:删除从光标前一个字符开始到行首的内容。
dw:删除一个单词。若光标处在某个词的中间,则从光标所在位置开始删至词尾。同dd命令一样,可在dw之前加一个数字n,表示删除n个指定的单词。
如果用户不小心进行了误删除操作,也不要紧,Vi提供了恢复误操作的命令,并且可以将恢复的内容移动,放在文本的任何地方。恢复命令用²
np,其中n为寄存器号。这是因为Vi内部有9个用于维护删除操作的寄存器,分别用数字1,2,¼
,9表示,它们分别保存以往用dd命令删除的内容。这些寄存器组成一个队列,例如最近一次使用dd命令删除的内容被放到寄存器1中;当下次再使用dd命令
删除文本内容时,Vi将把寄存器1的内容转存到寄存器2中,而寄存器1中又将是最近一次dd命令删除的内容。以此类推,Vi可以保存有最近九次用dd命令
删除的内容,而前面的用dd命令删除的内容则被抛弃。
[例18] 假设当前编辑文件为xu.c
/* this is a example */
#include <stdio.h>
void main( )
{
int i , j ;
printf( “ please input a number : / n ” );
scanf ( “ % d ” , &i ) ;
j = i + 100 ;
printf ( “ /n j = % d /n ” , j ) ;
return ;
}
我们对其进行如下操作:
1. 将光标移至文件第一行,按dd命令,此时文件第一行的内容被删除,且被删除的内容保存在寄存器1中;
2. 按5j使光标下移至第一个printf语句行;
3. 按dd命令将该行删除,此时寄存器1中将保存刚刚被删除的内容:
printf (“ please input a number :\ n ” );
而寄存器1原有的内容:
/* this is a example */
则被保存到寄存器2中;
在最末行模式下,也可以对文件内容进行删除,但它只能删除整行,一次可将某个指定范围内(起始行号,终止行号)的所有行全部删除。需要注意的是,用此种方
法进行删除时,Vi并不把所删内容放入寄存器中,因而当发生误删除操作时,不能用² np命令恢复,只能用u命令进行有限的恢复。
最后提一下,如何在文本输入方式时将所输入文本删除。用户使用<Ctrl+u>组合键即可,此时光标将返回插入开始的位置,并且Vi仍处于文本输入方式。
取消上一命令(Undo)
取消上一命令(Undo),也称复原命令,是非常有用的命令,它可以取消前一次的误操作或不合适的操作对文件造成的影响,使之回复到这种误操作或不合适操作被执行之前的状态。
取消上一命令有两种形式,在命令模式下键入字符u和U。它们的功能都是取消刚才输入的命令,恢复到原来的情况。小写u和大写U在具体细节上有所不同,二者
的区别在于,大写U命令的功能是恢复到误操作命令前的情况,即如果插入命令后使用U命令,就删除刚刚插入的内容;如果删除命令后使用U命令,就相当于在光
标处又插入刚刚删除的内容。这里把所有修改文本的命令都视为插入命令。也就是说,U命令只能取消前一步操作,如果用U命令撤消了前一步操作,当再按U键
时,并不是撤消再前一步的操作,而是撤消了刚才U命令执行的操作,也就是又恢复到第一次使用U命令之前的状态,结果是什么都没做。而小写u命令的功能是把
当前行恢复成被编辑前的状态,而不管此行被编辑了多少次。
[例19] 原来屏幕显示内容为:
#include <stdio.h>
main ( )
{
}
在命令模式下输入命令o,插入一新行,输入需要插入的内容后再按<Esc>回到命令模式,屏幕显示内容为:
#include <stdio.h>
main ( )
{
printf ( “ How do you do ! ” ) ;
}
若想取消这一插入操作,请按命令U后,屏幕恢复到原来显示的情况。
注意:对于取消命令仍可以再使用取消命令。这时会产生一种“负负得正”的效果,文件状态将恢复到第一次执行取消命令之前的状态,如同没做任何操作一般。例如在上例中,再使用一次命令U,屏幕将显示的内容仍为插入后的内容。
重复命令(Redo)
重复命令也是一个非常常用的命令。在文本编辑中经常会碰到需要机械地重复一些操作,这时就需要用到重复命令。它可以让用户方便地再执行一次前面刚完成的某个复杂的命令。
重复命令只能在命令模式下工作,在该模式下按“.”键既可。执行一个重复命令时,其结果是依赖于光标当前位置的。
[例20] 屏幕显示内容为:
#include <stdio.h>
main ( )
{
}
输入命令o,并输入一行内容后,再< Esc >返回到命令模式下,屏幕显示内容为:
#include <stdio.h>
main ( )
{
printf ( “ How do you do ! ” ) ;
}
此时输入命令“.”,屏幕显示内容为:
#include <stdio.h>
main ( )
{
printf ( “ How do you do ! ” ) ;
printf ( “ How do you do ! ” ) ;