本文最后更新于 2024-05-23,文章内容可能已经过时。

Linux vi 命令也就是指 vi 编辑器,它们是一个意思。vi 编辑器是 Linux/UNIX 环境下经典的编辑器。Linux vi 命令非常强大,熟练地使用它可以高效的编辑代码,配置系统文件等,是程序员和运维人员必须掌握的技能。

vi 可以执行输出、删除、查找、替换、块操作等众多文本操作,而且用户可以根据自己的需要对其进行定制。vi 编辑器只是一个文本编辑程序,它没有菜单,只有命令,且命令繁多。虽然学习这些命令比较费时费力,但是一旦你掌握了这些命令,你就会发现 vi 十分高效和强大,丝毫不逊色任何一款 Windows 上的编辑器,让我们从这套入门教程开始吧。其实,现在的 UNIX/Linux 大都使用 vim 代替了 vi。vim 是 vi 的增强版(vi Improved),与 vi 编辑器完全兼容,而且实现了很多增强功能。

vi 编辑器会依据文件扩展名或者是文件内的开头信息, 判断该文件的内容而自动的执行该程序的语法判断式,再以颜色来显示程序代码与一般信息。在某些发行版中,例如 CentOS 或者 Read Hat,当系统安装完毕后,vi/vim 编辑器默认就已经被安装了。在其他一些发行版中,例如 Debian 或者 Ubuntu,默认情况下 vi/vim 是不会被安装的,你需要自己手动安装。

接下来就是我自己学习Vi编辑器的一些记录笔记,本文纯属个人记录笔记,通篇大量参考引用于C语言中文网的Linux vi命令(vi编辑器)30分钟入门教程 ,各位有需求可以直接访问C语言中文网,里面确实很多知识干货。

1、vi工作模式以及模式切换

vi 编辑器有 3 种基本工作模式,分别是命令模式、文本输入模式和末行模式。下面详细介绍这 3 种模式。

(1)命令行模式

该模式是进入 vi 编辑器后的默认模式。任何时候,不管用户处于何种模式,按下 Esc键即可进入命令模式。
在命令模式下,用户可以输入 vi 命令,用于管理自己的文档。此时从键盘上输入的任何字符都被当做编辑命令来解释。若输入的字符是合法的 vi 命令,则 vi 在接受用户命令之后完成相应的动作。
但需注意的是,所输入的命令并不回显在屏幕上。若输入的字符不是 vi 的合法命令,vi 会响铃报警。

(2)文本输入模式

在命令模式下输入插入命令 i、附加命令 a、打开命令 o、修改命令 c、取代命令 r或替换命令 s都可以进入文本输入模式。
在该模式下,用户输入的任何字符都被 vi 当做文件内容保存起来,并将其显示在屏幕上。在文本输入过程中,若想回到命令模式下,按下 Esc键即可。

(3)末行模式

末行模式也称 ex 转义模式。
在命令模式下,用户按 :键即可进入末行模式下,此时 vi 会在显示窗口的最后一行(通常也是屏幕的最后一行)显示一个 :作为末行模式的说明符,等待用户输入命令。多数文件管理命令都是在此模式下执行的(如把编辑缓冲区的内容写到文件中等)。
末行命令执行完后,vi 自动回到命令模式。

1-1、vi工作模式之间的切换

如果需要从文本模式返回,则按下 Esc键即可。

在命令模式下输入 :即可切换到末行模式,然后输入命令。

vi 编辑器的 3 种模式的转换如下图所示:

2、vi编辑器的进入

打开一个 shell 终端,在说明符后输入 vi和 想要编辑(或建立)的文件名,便可进入 vi 编辑器,其格式如下:

vi filename

下面实例演示了进入 vi 编辑器编辑一个名为 test.c 的文件

$ vi test.c

屏幕显示如下:

|
~
~
~
~
~
~
~
~
~
~
~
~
"test.c" [New File]

| 表示光标

如果只输入 vi,而不带文件名,也可以进入 vi。这时编辑的文件是没有文件名的,所以在退出 vi 时,需要在退出命令后输入文件名,这样才能保证该文件被保存在磁盘中。
进入 vi 之后,首先进入的就是命令模式,也就是说等待命令输入而不是文本输入。这时输入的字母都将作为命令来解释。
光标表示 vi 编辑器的当前编辑位置停留在屏幕第 1 行首位上。其余各行行首均有一个 ~符号,表示该行为空行。
最后一行也称状态行,显示当前正在编辑的文件名及其状态。如本例是 [New File],表示 test.c 是一个新建的文件,其中还没有任何内容。如果 test.c 文件已在系统中存在,那么输入上述命令后,则在屏幕上显示出该文件的内容,并且光标停在第 1 行的首位,在状态行显示出该文件的文件名、行数和字符数。

2-1、文件打开光标定位

(1)如果希望在进入 vi 后,光标处于文件中特定的某行上,可在 vi 命令上加上行号和文件名,其格式如下:

vi +行号  文件名

如果希望在进入 vi 之后光标处于文件最末行,则只需去掉命令中 +后面的数字 n 即可,如下所示。

$ vi + 文件名 

(2)vi 编辑器支持模式匹配,也就是说用户可以在命令中指定一个模式串。之后进入 vi 后,光标就处于文件中第一个与指定模式串相匹配的那行上。其格式如下:

vi +/模式字符串  文件名

进入文件后光标会停留在指定的字符串,字符串会高亮显示,如果要取消高亮显示,可以在末行模式使用以下命令:

:set nohlsearch

2-2、通配符打开文件

使用 vi 可以同时编辑多个文件,只要在进入 vi 的命令中写入所要操作的文件即可,还可以使用通配符,其格式如下:

vi 需要打开文件的通配符

如果需要打开当前目录下所有的C语言源文件,则可以使用以下命令:

$ vi *.c

如果在一个C语言的工程中需要快速定位某函数并且对其进行编辑,则可以同时使用打开文件的通配符和模式匹配字符串。

实例

演示了如何在一个完整的工程中快速定位某个函数并且对其进行编辑。

(1)在 vi 编辑器中编辑 common.h 程序如下:

#include <stdio.h>
#include <stdlib.h>
extern void swap(int *a, int *b);

(2)在 vi 编辑器中编辑 swap.c 程序如下:

#include "common.h"
void swap(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

(3)在 vi 编辑器中编辑 main.c 程序如下。

#include "common.h"
int main(void)
{
    int a, b;
    sacnf("%d %d", &a, &b);
    swap(a, b);
    printf("%d, %d\n", a, b);
    return 0;
}

(4)保存并且退出vi编辑器

(5)打开该程序的所有源文件,并且将显示位置定位在main()函数上

$vi +/main *.c *.h

一个C程序的源文件一般只包括两种,即头文件(.h文件)和源文件(.c文件)。因此该命令执行后,将打开目录内所有的 .h文件和 .c文件,并且将当前编辑文件设置为 main.c 文件,光标置于 main.c 文件的第 3 行。

3、vi修改文件内容(文件修改命令)

在命令模式下用户输入的任何字符都被 vi 当作命令加以解释执行,使用“文本修改命令”可以将 vi 切换到文本输入模式,这时用户输入的字符将被当作是文本内容。文本修改命令有以下几种。

3-1、插入文本命令:i和I

i 命令将文本插入到光标所在位置前。此时 vi 处于文本插入状态,屏幕最下行显示 “--INSERT--”说明信息。下面实例演示了使用 i 命令插入文本。

hello world

光标位于 w 之上,要在其前面插入。

real-

使用 i 命令,并输入相应文本后,屏幕显示如下:

hello real-world 

I 命令将文本插入当前行的行首。当输入 I 命令后,光标自动移到该行的行首。下面实例演示了使用 I 命令插入文本。

hello world 

光标同样位于 w 的之上,要在其前面插入。

real-

使用 I 命令,并输入相应文本后,屏幕显示如下:

real-hello world

3-2、追加文本命令:a和A

a 命令将新文本追加到光标当前所在位置之后。下面示例演示了使用 a 命令追加文本。

hello world

光标位于“ ”(空格字符)之上,要在其后面追加。

real- 

使用 a 命令,并输入相应文本后,屏幕显示如下:

hello real-world

A 命令将新文本追加到所在行的行尾。当输入 A 命令后,光标自动移到该行的行尾。下面示例演示了使用 A 命令追加文本。

hello world

光标位于“ ”(空格字符)之上,要在其后面追加。

real- 

使用 A 命令,并输入相应文本后,屏幕显示如下:

hello worldreal- 

3-3、空行插入命令:o 和 O

若用户希望在某行之前或某行之后插入一些新行,则应使用 o 命令。

  • o 命令将在光标所在行的下面插入一个空行,并将光标置于该行的行首。
  • O 命令在光标所在行的上面插入一个空行,并将光标置于该行的行首。

4、vi文本删除命令(删除文件内容)

vi 编辑器可以在编辑模式和命令模式下删除文本。传统的文本删除是在编辑模式下,使用退格键或 Del 键删除文本。在命令模式下,vi 提供了许多删除命令。常用的命令表如下:

文本删除命令命令的意义文本删除命令命令的意义
x删除光标处的字符d(删除到上一句开始的所有字符
X删除光标前面的字符d)删除到下一句开始的所有字符
dd删除光标所在的整行d{删除到上一段开始的所有字符
D或d$删除从光标所在处开始到行尾的内容d}删除到下一段开始的所有字符
d0删除从光标前一个字符开始到行首的内容d <CR>删除包括当前行所在内的两行字符
dw删除一个单词

删除文本的命令可以分为删除单个字符和删除多个字符两类。其中,删除单个字符的命令包括下面两种情况。

  • x 命令:删除光标处的字符。若在 x 之前加上一个数字 n,则删除从光标所在位置开始向右的 n 个字符。
  • X 命令:删除光标前面的字符。若在 X 之前加上一个数字 n,则删除从光标前面那个字符开始向左的 n 个字符。

删除多个字符的命令包括下面几种情况。* dd 命令:该命令删除光标所在的整行。在 dd 前可加上一个数字 n,表示删除当前行及其后 n-1 行的内容。

  • D 命令或 d$ 命令:两个命令功能一样,都是删除从光标所在处开始到行尾的内容。
  • d0 命令:该命令删除从光标前一个字符开始到行首的内容。
  • dw 命令:该命令删除一个单词。若光标处在某个词的中间,则从光标所在位置开始删至词尾。同 dd 命令一样,可在 dw 之前加一个数字n,表示删除 n 个指定的单词。
  • d( 命令:该命令删除到上一句开始的所有字符。
  • d) 命令:该命令删除到下一句开始的所有字符。
  • d} 命令:该命令删除到上一段开始的所有字符。
  • d{ 命令:该命令删除到下一段开始的所有字符。
  • d<CR> 命令:该命令(<CR>表示回车)删除包括当前行在内的两行字符。

5、vi文本复制命令

vi 编辑器可以在编辑模式和命令模式下复制文本。常用的复制文本的命令如下表所示。

文本复制命令命令的意义文本复制命令命令的意义
yy复制光标所在的整行y{复制到上一段的开始
Y 或 y$复制从光标所在处开始到行尾的内容y}复制到下一段的开始
y0复制从光标前一个字符开始到行首的内容y <CR>复制包括当前行在内的两行内容
y(复制到上一句的开始yw复制一个单词
y)复制到下一句的开始
  • yy 命令:复制光标所在的整行。在 yy 前可加一个数字 n,表示复制当前行及其后 n-1 行的内容。
  • Y 或 y$ 命令:两命令功能一样,都是复制从光标所在处开始到行尾的内容。
  • yw 命令:复制一个单词。若光标处在某个词的中间,则从光标所在位置开始复制至词尾。同 yy 命令一样,可在 yw 之前加一个数字 n,表示复制 n 个指定的单词。
  • y) 命令:复制到下一句幵始的所有字符。
  • y} 命令:复制到下一段开始的所有字符。
  • y<CR> 命令(<CR> 表示回车):复制包括当前行在内的两行内容。

与文本复制有关的命令分为两类。

  1. 文本粘贴命令
  • p 命令:粘贴命令,粘贴当前缓冲区中的内容。
  1. 文本选择命令
  • v 命令:在命令模式下进行文本选择。在需要选择的文本的起始处按下 v 键进入块选择模式,然后移动光标到块尾处。这之间的部分被高亮显示,表示被选中。
  • V 命令:在命令模式下按行进行文本选择。在需要选择的文本的第一行按下 V 键,然后移动光标到块的最后一行。这之间的所有行被高亮显示,表示被选中。

vi 编辑器支持最近编辑内容的恢复,但是由于 vi 编辑器使用寄存器存放最近内容,所以恢复能力有限。vi 编辑器使用 9 个寄存器,可以存放已经删除的 9 个最近内容,这些内容可以被恢复。

实例

#include <stdio.h>
int main(void)
{
  int i, j;
  printf("please input a number: \n");
  scanf(" % d ", &i);
  j = i + 100;
  printf("\nj = %d\n", j);
  return 0;
}

现在对其进行如下操作。

  1. 将光标移至文件第 1 行,输入 dd 命令,此时文件第 1 行的内容被删除,且被删除的内容保存在寄存器 1 中。这行的内容是#indude <stdio.h>,被保存在寄存器 1 中。
  2. 将光标下移至第 1 个 printf 语句行,输入 dd 命令将该行删除,此时寄存器 1 中将保存刚刚被删除的内容。也就是说#indude <stdio.h>被保存到了寄存器 2 中,而printf("please input a number: \n");这一行的内容被保存在了寄存器 1 中。

6、vi撤销命令(u和U),撤销上一次的操作

撤销命令是非常有用的,它可以撤销前一次的误操作或不合适的操作对文件造成的影响。撤销命令分为以下两种。

  • u 命令:该命令撤销上一次所做的操作。多次使用 u 命令会一步一步依次撤销之前做过的操作(在一次切换到文本输入模式中输入的所有文本算一次操作)。
  • U 命令:该命令会一次性撤销自上次移动到当前行以来做过的所有操作,再使用一次 U 命令则撤销之前的 U 命令所做的操作,恢复被撤销的内容。

实例

(1)在 vi 编辑器中编辑以下代码:

#include <stdio.h>
int main(void)
{
    printf("hello world\n");
    return 0;
}

(2)光标停留在 h 的左侧,在命令模式下输入命令 o 插入一新行,输入需要插入的内容后再按下 Esc 键回到命令模式,屏幕显示内容如下:

#include <stdio.h>
int main(void)
{
    printf("hello world\n");
    printf("hello real-world\n");
    printf("hello world\n");
    return 0;
}

(3)使用命令 U 后,取消所有操作,屏幕显示为:

#include <stdio.h>
int main(void)
{
    printf("hello world\n");
    return 0;
}

(4)使用命令 u 后,仅取消第 2 个输入的串 printf("hello world\n");,屏幕显示为:

#include <stdio.h>
int main(void)
{
    printf("hello world\n");
    printf("hello real-world\n");
    return 0;
}

7、vi重复命令(重复上次操作)

当用户在文本编辑中碰到需要机械地重复一些操作的时候,重复命令就派上了用场。它可以让用户方便地再执行一次前面刚完成的某个复杂的命令。重复命令只能在命令模式下工作,在该模式下按下 .键即可。下面实例演示了使用重复命令。

  1. 在 vi 编辑器中编辑以下代码:

    #include <stdio.h>
    int main (void)
    {
      return 0;
    }
    
  2. 让光标位于 return 0;所在的行,输入命令 O,并输入一行内容后,再按下 Esc 键回到命令模式下,屏幕显示内容为:

    #include <stdio.h>
    int main(void)
    {
        printf ("http://c.biancheng.net\n");
        return 0;
    }
    
  3. 此时输入命令 .,重复上次键入 printf ("http://c.biancheng.net\n");的操作,屏幕显示内容为:

    #include <stdio.h>
    int main (void)
    {
        printf ("http://c.biancheng.net\n");
        printf ("http://c.biancheng.net\n");
        return 0;
    }
    

8、vi退出命令

命令q

在末行模式下,输入命令如下:

:q

如果退出时当前编辑文件尚未保存,则 vi 并不退出,而是继续等待用户的命令,并且会在显示窗口的最末行说明如下信息:

No write since last change (use! to overrides)

说明:当用户不清楚自己当前编译的文件是否被修改时,可以使用该命令进行测试,而不必担心因为误操作导致文件数据丢失。

命令q!

在末行模式下,输入命令如下:

:q!

该命令不论文件是否改变都会强行退出 vi 编辑器,对于此命令用户应当慎用。

命令w

在末行模式下,输入命令如下:

:w 新文件名

vi 保存当前编辑文件,但并不退出,而是继续等待用户输入命令。在使用 w 命令时,可以再给当前编辑文件起一个新的文件名。这个功能相当于将该文件另存为为一个新的文件。下面实例演示了将 main.c 文件另存为 test.c 文件。

#include "common.h"
int main(void)
{
    int a, b;
    sacnf("%d %d", &af &b);
    swap (a, b);
    printf ("%d, %d\n", a, b);
    return 0;
}
:w test.c

保存之后使用 :q命令退出 vi 编辑器,使用 ls 命令查看当前目录下的文件时,会发现多了一个 test.c 文件,该文件的内容和 main.c 一致。可以使用 cat 命令查看该文件的内容,main.c 文件的内容不受影响。若指定的新文件是一个已存在的文件,则 vi 在显示窗口的状态行给出如下说明信息:

File exists (use! to override)

说明:这样做同样可以防止因误操作覆盖已经存在的文件,用户可以选择另外的文件名来保存当前文件。

命令w!

在末行模式下,输入命令如下:

:w! 新文件名

说明:该命令与 :w命令相同,所不同的是,即使指定的新文件存在,vi 编辑器也会用当前编辑文件对其进行替换,而不再询问用户。因此,此命令同样要慎用。vi 将先保存文件,然后退出 vi 返回到 shell。如果当前文件尚未取名,则需要现指定一个文件名。

命令wq

在末行模式下,输入命令如下:

:wq

vi 将先保存文件,然后退出 vi 返回到 shell。如果当前文件尚未取名,则需要现指定一个文件名。

命令x

在末行模式下,输入命令如下:

:x

说明:若当前编辑文件曾被修改过,则 vi 会保存该文件。否则 vi 直接退出,不保存该文件。

9、vi字符替换命令(r和R命令)

vi 编辑器可以对文本进行替换操作,其命令如下。

r命令

该命令将当前光标所指的字符替换为提供的字符。可以在该命令之前加上数字 n,表示将从当前字符开始的 n 个字符替换为提供的字符。下面实例演示了 r 命令的使用。

  1. 在 vi 编辑器中编辑以下代码:
    #include <stdio.h>
    int add(int a, int b)
    {
        return a + b;
    }
    int main(void)
    {
        int i, sum;
        for (i = 0; i < 3 ; i++){
            sum = add(i, i + 1);
            printf("%d\n", sum);
        }
    }
    "test.c" 13L, 170C
    
  2. 将光标移至 main 的首字符a上,在命令行模式下输入 4rb,显示如下:
#include <stdio.h>
int add(int a, int b)
{
    return a + b;
}
int mbbbbvoid)
{
    int i, sum;
    for (i = 0; i < 3; i++){
        sum = add(i, i + 1);
        printf("%d\n", sum);
    }
}
"test.c" 13L, 170C

R命令

该命令会让 vi 进入 replace 模式。在此模式下,每个输入的字符都会替换当前光标下的字符,直到输入 <Esc> 结束该模式。

10、vi光标移动命令

vi 最基本的移动光标命令有 4 个,如下表所示。

光标移动命令命令意义光标移动命令命令意义
h光标左移一个字符k光标上移一行
j光标下移一行l光标右移一个字符

10-1、按行移动光标

在 vi 编辑器中,光标可以按行移动,一次性移动一行或者多行。

H命令

H 命令将光标移至当前屏幕的第 1 行,而不是整个文件的第 1 行。若在 H 命令之前加 上数字 n,则将光标移至第 n 行的行首。下面实例演示了使用 H 命令快速移动光标。

  1. 在 vi 编辑器中编辑以下代码:
    #include <stdio.h>
    int add(int a, int b)
    {
        return a + b;
    }
    int main (void)
    {
        int i;
        int sum;
        for (i = 0; i < 3; i++){
            sum = add(i, i + 1);
            printf("%d\n", sum);
        }
    }
    
  2. 在命令行模式下,输入 H 命令,光标位于第一行开头,如下所示:
    #include <stdio.h>
    int add(int a, int b)
    {
        return a + b;
    }
    int main (void)
    {
        int i;
        int sum;
        for (i = 0; i < 3; i++){
            sum = add(i, i + 1);
            printf("%d\n", sum);
        }
    }
    
  3. 在命令行模式下,输入 H 命令,光标位于第一行开头,如下所示:
    #include <stdio.h>
    int add(int a, int b)
    {
        return a + b;
    }
    int main (void)
    {
        int i;
        int sum;
        for (i = 0; i < 3; i++){
            sum = add(i, i + 1);
            printf("%d\n", sum);
        }
    }
    

M命令

M 命令将光标移至屏幕显示文件的中间行的行首。即如果当前屏幕已经充满,则移动到整个屏幕的中间行;否则,移动到显示文本的那些行的中间行。
利用此命令可以快速地将光标从屏幕的任意位置移至屏幕显示文件的中间行的行首。

、L命令

L 命令将光标移至屏幕显示文件的最底行的行首。即如果文件内容需要超过一个屏幕显示时,该命令将光标移至屏幕上最底行的行首;否则该命令将光标移至文件最后一行的行首。可见,利用此命令可以快速准确地将光标移至屏幕底部或文件的最后一行。
若在 L 命令之前加上数字 n,则将光标移至从屏幕底部算起第 n 行的行首。

G命令

在全文的范围内移动光标,此时的光标移动范围不再受屏幕的限制。例如,在上例中,在命令模式下输入命令 5G 之后光标将移到第 5 行的行首。

10-2、按字移动光标

vi 编辑器提供 3 组命令,这 3 组命令每次可以使光标按字移动。这 3 组命令分别如下。

w和W命令

w 和 W 命令将光标右移至下一个字的字首。这两个命令的区别在于:

  • w 命令所指的字是指英文单词、标点符号和非字母字符;
  • W 命令所指的字是指两个空格之间的任何内容。

下面实例演示了两个命令的区别。

屏幕上显示如下:

printf("hello world!\n");

将光标停留在 printf 的 p字符之上,使用 w 命令之后,光标将移到下一个字 (之上

让光标再次停留到 printf 的 p字符之上,使用 W 命令之后,光标移动到下一个 w之上

e和E命令

如果光标起始位置处于字内,则 e 和 E 命令将把光标移到本字字尾;如果光标起始位置处于字尾,则 e 和 E 命令将把光标移动到下一个字的字尾。

e 和 E 命令的区别在于:

  • e 命令所指的字是指英文单词、标点符号和非字母字符;
  • E 命令所指的字是指两个空格之间的任何内容。

下面实例演示了两个命令的区别。

屏幕上显示如下:

printf("hello real-world!\n");

将光标停留在 real 的字符 a之上,使用 e 命令之后,把光标移到字尾 l之上

让光标再次停留到 real 的字符 a之上,使用 E 命令后,光标将移动到字尾的 ;之上:

b和B命令

如果光标处于所在字内,则 b 和 B 命令将把光标移至本字字首;如果光标处于所在字字首,则 b 和 B 命令将把光标移到上一个字的字首。两个命令的区别在于:

  • b 命令所指的字是指英文单词、标点符号和非字母字符;
  • B 命令所指的字是指两个空格之间的任何内容。

下面实例演示了两个命令的区别。

屏幕上显示如下:

printf("hello real-world!\n");

将光标停留在 world 的字符 o之上,使用 b 命令之后,光标将移到字首的 w之上;

让光标再次停留到 world 的字符 o之上,使用 B 命令之后,光标将移动到字首的 r之上

10-3、按段落移动光标

在 vi 编辑器中,一个段落被定义为是以一个空白行开始和结束的片段。按段落移动光标的命令有以下两种。

  • {命令:该命令将光标向前移至上一个段落的开头。
  • }命令:该命令将光标向后移至下一个段落的开头。

11.文本移动命令

在 vi 编辑器中可以方便地将某个范围内的文本行左右移动或从一个地方移至另外一个地方。文本行左右移动的命令有 4 个。

> 命令

>命令将指定的正文行向右移动,通常是右移 8 个空格。移动正文行的范围由光标所在行和随后输入的光标移动命令所限定。

命令的使用格式如下:

>n

n 表示光标所在位置后面的文本行数。也可以不写 n,此时默认为 1;换句话说,只使用 >命令将会移动光标所在的文本行,以及下一个文本行。

如果只想移动光标所在的文本行,可以写 >0

需要注意的是,指定的数字是需要移动的行的数目,并不是要右移的空格数。下面实例演示了将一段代码整体右移。

1.在 vi 编辑器中编辑下面代码,将光标定位到第二行,屏幕显示如下:

#include <stdio.h>
int main(void)
{
    int a = 1, b = 2, add, sub, mul, div;
    add = a + b;
    sub = a - b;
    mul = a * b;
    div = a / b;
    printf("add %d, sub %d, mul %d, div %d\n", add, sub, mul, div);
    return 0;
}

2.输入 >6回车后,屏幕显示为:

#include <stdio.h>
        int main(void)
        {
            int a = 1, b = 2, add, sub, mul, div;
            add = a + b;
            sub = a - b;
            mul = a * b;
            div = a / b;
    printf("add %d, sub %d, mul %d, div %d\n", add, sub, mulf div);
    return 0;
}

< 命令

<命令将指定的正文行向左移动。其使用方式与命令相同,但是方向相反。

>> 命令

>>该命令将光标所在行右移 8 个空格。如果在 >>命令之前给出一个数字 n,例如 4,则表示光标当前行及其下面的 3 行(共4行)都右移 8 个空格。下面实例演示了使用 >>命令移动文本。

  1. 在 vi 编辑器中编辑以下代码,并且将光标停留在第 4 行上:

    #include <stdio.h>
    int main(void)
    {
    int a = 1, b = 2, add, sub, mul, div;
    add = a + b;
    sub = a - b;
    mul = a * b;
    div = a / b;
    printf(nadd %d, sub %d, mul %d, div %d\n", add, sub, mulf div);
    return 0;
    }
    
  2. 输入 7>>后,屏幕显示为:

    #include <stdio.h>
    int main(void)
    {
                int a = 1, b = 2, add, sub, mul, div;
                add = a + b;
                sub = a - b;
                mul = a * b;
                div = a / b;
                printf("add %d, sub %d, mul %df div %d\n", add, sub, mul, div);
                return 0;
    }
    

<<命令

<<命令将光标所在行左移 8 个空格。其使用与 >>命令相同,但是移动方向相反。

12、vi文本跨行移动(m命令)

vi 编辑器提供文本的跨行移动。这个操作允许用户将某一行的文本内容移动到指定位置。

vi 编辑器使用 m 命令实现文本的跨行移动。该命令的使用方法为:

imj

表示把第 i 行移至第 j 行的下方。下面实例演示了 m 命令的使用。

  1. 在 vi 编辑器中编辑以下代码:#include <stdio.h>
    int main(void)
    {
    printf("hello world\n");
    return 0;
    }
    
  2. 在末行模式下输入命令5m2,将第 5 行的 printf() 函数调用移动到第 2 行的下方,显示如下:
    #include <stdio.h>
    int main(void)
       return 0;
    {
       printf("hello world\n");
    }
    

13、vi屏幕滚动命令(滚屏命令)

如果文件太大,一个屏幕不能将其内容完全显示出来,vi 编辑器会采用分屏显示的方法。使用屏幕命令可以以屏幕为单位移动光标,方便地完成文件的滚屏和分页。

需要注意的是,屏幕命令不是光标移动命令,不能作为文本限定符用于删除命令中。在命令模式下和文本输入模式下均可以使用滚屏和分页命令。滚屏和分页命令如下表所示。

滚屏和分页命令命令意义
Ctrl+u将屏幕向前(文件头方向)翻滚半屏
Ctrl+d将屏幕向后(文件尾方向)翻滚半
Ctrl+f将屏幕向文件尾方向翻滚一整屏
Ctrl+b将屏幕向文件首方向翻滚一整屏

可以在滚屏和分页命令之前加上一个数字 n,表示屏幕向前或向后翻滚 n 行,或者屏幕向前或向后移动 n 页。这些设置会被 vi 编辑器记住,下次用户在使用滚屏和分页命令时,还会滚动和上次设置相同的行数或者页数。

14、vi字符串检索(查找)命令

vi 编辑器提供简单的字符串检索功能。在末行模式下,用户可以使用不同的命令对需要的字符串进行查找。查找命令有 5 种。

/ 命令

/命令的格式为:

/string

/命令从光标处开始向后寻找字符串 string。

? 命令

? 命令的格式为:

?string

? 命令从光标处开始向前寻找字符串 string。

n 命令

n 命令重复上一条检索命令。

N 命令

N 命令重复上一条检索命令,但检索方向改变。例如上次的检索命令是向前检索,那么此次检索的方向是向后;如果上次的检索命令是向后检索,那么此次检索的方向是向前。

g/ 命令

g/ 命令的格式是为:

g/string

检索 string。g/命令使光标停止在第一个检索到的 string 串的行首。下面实例演示了 g/命令的用法。

  1. 在 vi 编辑器中编辑以下代码:

    #include <stdio.h>
    int add(int a, int b)
    {
      return a + b;
    }
    int main(void)
    {
      int i, sum;
      for (i = 0; i < 3; i++){
        sum = add(i, i + 1);
        printf("%d\n", sum);
      }
    }
    
  2. 在末行模式下输入 g/main,显示如下:

    #include <stdio.h>
    int add(int a, int b)
    {
      return a + b;
    }
    int main(void)
    {
      int i, sum;
      for (i = 0; i < 3 ; i++){
        sum = add(i, i + 1);
        printf("%d\n", sum);
      }
    }
    ~
    ~
    ~
    ~
    ~
    :g/main
    int main(void)
    请按 ENTER 或其它命令继续
    

按下回车键,光标将移动到 int main(void)的行首。

15、vi字符串替换命令

vi 编辑器提供简单的字符串替换命令,在末行模式下可以使用替换命令,其命令格式如下:

[range]s/s1/s2/ [option]
  • [range] 表示检索范围,省略时表示当前行。下面是一些检索范围的例子。
    • 1,10表示从第 1 行到 10 行。
    • %表示整个文件,同1, $
    • . ,$从当前行到文件尾。
  • s 为替换命令。
  • s1 要被替换的串,s2 为替换的串。
  • option 表示选项:
    • /g表示在全局文件中进行替换。
    • /c表示在每次替换之前需要用户进行确认。
    • 省略时仅对每行第一个匹配串进行替换。

下面实例演示了字符串替换命令,将第 10~22 行的 printf 标识符替换为 PRINT。

  1. 在 vi 编辑器中编辑以下代码:
    int main(void)
    {
        struct stat buf; /*存储文件状态信息*/
        if(stat("s1", &buf) == -1) {
            perror ("fail to stat");
            exit(1);
        }
        printf("permission : %d\n", buf.st_mode);
        printf("inode number : %d\n", buf.st_ino);
        printf("device number : %d\n", buf.st_dev);
        printf("r-device number : %d\n", buf.st_rdev);
        printf("link : %d\n", buf.st_nlink);
        printf("uid : %d\n", buf.st_uid);
        printf("gid : %d\n", buf.st_gid);
        printf("file size : %d\n", buf.st_size);
        printf("access time : %d\n", buf.st_atime);
        printf("motify time : %d\n", buf.st_mtime);
        printf("change time : %d\n", buf.st_ctime);
        printf("buf size : %d\n", buf.st_blksize);
        printf("block size : %d\n", buf.st_blocks);
        return 0;
    }
    
  2. 在末行模式下输入以下替换命令:
10,22s/printf/PRINT/g

屏幕显示如下:

int main(void)
{
    struct stat buf; /*存储文件状态信息*/
    if(stat("s1", &buf) == -1) {
        perror ("fail to stat");
        exit(1);
    }
    PRINTF("permission : %d\n", buf.st_mode);
    PRINTF("inode number : %d\n", buf.st_ino);
    PRINTF("device number : %d\n", buf.st_dev);
    PRINTF("r-device number : %d\n", buf.st_rdev);
    PRINTF("link : %d\n", buf.st_nlink);
    PRINTF("uid : %d\n", buf.st_uid);
    PRINTF("gid : %d\n", buf.st_gid);
    PRINTF("file size : %d\n", buf.st_size);
    PRINTF("access time : %d\n", buf.st_atime);
    PRINTF("motify time : %d\n", buf.st_mtime);
    PRINTF("change time : %d\n", buf.st_ctime);
    PRINTF("buf size : %d\n", buf.st_blksize);
    PRINTF("block size : %d\n", buf.st_blocks);
    return 0;
}

vi 编辑器在执行替换命令指令时,可以进行简单的模式匹配,其匹配模式如下:

\<word

替换以 word 开始的单词的 word 部分。例如:

%s/\<abc/cde

表示将以 abc 开头的单词替换为以 cde 开头。

下例演示了这种替换操作,更改 stat 结构的变量名,将整个文件中的 buf 替换为 stat_buf。

  1. 在 vi 编辑器中编辑以下代码:
    int main(void)
    {
        struct stat buf; /*存储文件状态信息*/
        if(stat("s1", &buf) == -1) {
            perror ("fail to stat");
            exit(1);
        }
        printf("permission : %d\n", buf.st_mode);
        printf("inode number : %d\n", buf.st_ino);
        printf("device number : %d\n", buf.st_dev);
        printf("r-device number : %d\n", buf.st_rdev);
        printf("link : %d\n", buf.st_nlink);
        printf("uid : %d\n", buf.st_uid);
        printf("gid : %d\n", buf.st_gid);
        printf("file size : %d\n", buf.st_size);
        printf("access time : %d\n", buf.st_atime);
        printf("motify time : %d\n", buf.st_mtime);
        printf("change time : %d\n", buf.st_ctime);
        printf("buf size : %d\n", buf.st_blksize);
        printf("block size : %d\n", buf.st_blocks);
        return 0;
    }
    
  2. 在末行模式下输入命令:
%s/\<buf/stat_buf/g

屏幕显示如下:

int main(void)
{
    struct stat stat_buf; /*存储文件状态信息*/
    if(stat("s1", &stat_buf) == -1) {
        perror ("fail to stat");
        exit(1);
    }
    printf("permission : %d\n", stat_buf.st_mode);
    printf("inode number : %d\n", stat_buf.st_ino);
    printf("device number : %d\n", stat_buf.st_dev);
    printf("r-device number : %d\n", stat_buf.st_rdev);
    printf("link : %d\n", stat_buf.st_nlink);
    printf("uid : %d\n", stat_buf.st_uid);
    printf("gid : %d\n", stat_buf.st_gid);
    printf("file size : %d\n", stat_buf.st_size);
    printf("access time : %d\n", stat_buf.st_atime);
    printf("motify time : %d\n", stat_buf.st_mtime);
    printf("change time : %d\n", stat_buf.st_ctime);
    printf("stat_buf size : %d\n", stat_buf.st_blksize);
    printf("block size : %d\n", stat_buf.st_blocks);
    return 0;
}

16、vi窗口切分命令

在末行模式中,输入 split 命令即可实现窗口的切分,其命令格式如下:

: split文件名

其中 :表示进入末行模式。

split 也可简写为 sp。这时窗口切分为上下两部分,下半部分对应原来的文件,上半部分对应新打开的文件。

有时用户需要在多窗口之间进行切换,vi 编辑器提供一组命令支持用户切换多个窗口,其命令如下表所示。

切换命令命令的意义
Ctrl+w,然后 j移动光标到下面的一个窗口
Ctrl+w,然后 k移动光标到上面的一个窗口
Ctrl+w,然后 k关闭当前窗口
Ctrl+w,然后 w移动光标到另一个窗口

17、vi属性设置命令

vi 编辑器提供可以设置其环境属性的命令,这些命令如下所示。

行号设置命令

:set nu (nonu)

该命令显示行号(或者不显示行号)。

显示设置命令

:set hlsearch (nohlsearch)

该命令设定搜寻字符串反白显示(或者不反白显示)。

语法缩进命令

:set autoindent

该命令显示程序语法自动缩进。

文件存储命令

:set backup(nobackup)

该命令自动储存备份文件(或者不自动备份文件)。

显示选项命令

:set all

该命令显示所有的选项。

语法高亮命令

:syntax on (off)

该命令实现程序语法高亮显示(或者不高亮显示)。

大小写区分命令

:set ignorecase(noignorecase)

该命令忽略大小写(或者区分大小写)。

注意:所有的命令都需要在末行模式下输入。