how to debug with some tips or tools

调试-linux程序设计

clip_image001

错误查找及纠正

有几种原因会造成程序的缺陷,针对每种原因,都有一些建议的方法来查找和纠正。比如功能定义错误,设计规划错误和代码编写错误

clip_image003

程序调试的5个阶段

clip_image005

使用printf来排错

       相信这个方法是N多人使用的方法

使用-Wall选项来排错

       在使用gcc编译的时候加上-Wall选项,可以提前发现很多的warnings

注释法

       将怀疑有错的程序块注释起来,查看一下结果,如此反复即可。

使用内置宏__FILE__

       灵活使用内置宏__LINE__,__FILE__,__DATE____TIME可以很快速地定位问题所在。

使用assert断言来预防错误的发生

       诸如分母不能为0的情况。

专业级别的gdb调试

       关于gdb的调试,参考:

clip_image006 clip_image008 clip_image010

静态分析调试工具

ctags

       参考:http://ctags.sourceforge.net/

       相信使用过vim的童鞋都晓得这个工具,ctagsGenerate tag files for source code)是vim下方便代码阅读的工具。尽管ctags也可以支持其它编辑器,但是它正式支持的只有VIM。并且VIM中已经默认安装了Ctags,它可以帮助程序员很容易地浏览源代码。

ctags 最先是用来生成C代码的tags文件,后来扩展成可以生成各类语言的tags, 有些语言也有专有的tags生成工具(比如javajtags, python ptags)

clip_image012

cxref

参考:http://www.gedanken.demon.co.uk/cxref/

Cxref是一款在LaTeXHTMLRTFSGML中将C代码生成文件的程序,包括从C程序源代码的交叉引用。它用于ANSI C,包含大多数gcc扩展,可以从代码中的注释进行生成适当格式的程序文档,交叉引用来自于代码本身并不需要额外的工作。

clip_image014

cflow

参考:http://www.gnu.org/software/cflow/

GNU cflow analyzes a collection of C source files and prints a graph, charting control flow within the program.

GNU cflow is able to produce both direct and inverted flowgraphs for C sources. Optionally a cross-reference listing can be generated. Two output formats are implemented: POSIX and GNU (extended).

Input files can optionally be preprocessed before analyzing.

The package also provides Emacs major mode for examining the produced flowcharts in Emacs.

clip_image016

动态分析调试工具

gprof

gprofGNU profiler工具。可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间。也可以显示调用图,包括函数的调用关系,每个函数调用花费了多少时间。还可以显示注释的源代码,是程序源代码的一个复本,标记有程序中每行代码的执行次数。

gprof编译程序


在编译或链接源程序的时候在编译器的命令行参数中加入“-pg”选项,编译时编译器会自动在目标代码中插入用于性能测试的代码片断,这些代码在程序在运行时采集并记录函数的调用关系和调用次数,以及采集并记录函数自身执行时间和子函数的调用时间,程序运行结束后,会在程序退出的路径下生成一个gmon.out文件。这个文件就是记录并保存下来的监控数据。可以通过命令行方式的gprof或图形化的Kprof来解读这些数据并对程序的性能进行分析。另外,如果想查看库函数的profiling,需要在编译是再加入“-lc_p”编译参数代替“-lc”编译参数,这样程序会链接libc_p.a库,才可以产生库函数的profiling信息。如果想执行一行一行的profiling,还需要加入“-g”编译参数。
例如如下命令行:
gcc -Wall -g -pg -lc_p example.c -o example

clip_image018

工具lint

lint是最著名的C语言工具之一,是由贝尔实验室SteveJohnson1979PCC(PortableC Compiler)基础上开发的静态代码分析,一般由UNIX系统提供。与大多数C语言编译器相比,lint可以对程序进行更加广泛的错误分析,是一种更加严密的编译工具。最初,lint这个工具用来扫描C源文件并对源程序中不可移植的代码提出警告。但是现在大多数lint实用程序已经变得更加严密,它不但可以检查出可移植性问题,而且可以检查出那些虽然可移植并且完全合乎语法但却很可能是错误的特性。

随着历史的推移,Lint后来形成了一系列的工具,包括PC-Lint/FlexeLint(Gimpel),LintPlus(Cleanscape)以及Splint

clip_image019

内存调试工具ElectricFence

clip_image020

参考:http://directory.fsf.org/wiki/Electric_Fence

       实际运行环境中经常比较困扰的问题是内存产生轻微越界,但是并没有立刻产生问题, 给调查带来很大难度。

如果程序问题调查没有头绪,可以借助 Electric Fence (简称 Efence )工具检查内存问题并产生 CORE 文件,比较精确的定位问题场所。

       在发生如下问题的情况下此工具会转储 CORE

1 )动态分配内存边界外的读写操作

2 )访问已经 free 的内存

3 free 的地址不是 malloc() 分配的

Valgrind

       参考:http://valgrind.org/

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。

clip_image021

vim–bonus hacks

vim-额外小技巧

clip_image001

给每行加上一个标号

比如,对于文本

package main

import “fmt”

func main() {

fmt.Println(“Hello, world!”)

}

经过下面的操作会变成

* package main

* import “fmt”

* func main() {

* fmt.Println(“Hello, world!”)

* }

步骤:

1.        进入可视模式CTRL+V,选择第一个字符,把几行全选上;

2.        输入I,注意是大写的i

3.        然后按下TAB

4.        输入*并按下空格键;

5.        上面的步骤只会对第一行有效;

6.        重点来了,此时按下ESC两次,即ESC ESC将会把所有的行加上*

vim设置为默认的编辑器

clip_image002

使用update-alternatives – -set editor <pathOfVim>比如我的也是大部分就是update-alternatives – -set editor /usr/bin/vim

缩进代码块

对于

package main

import “fmt”

func main()

{

fmt.Println(“Hello, world!”)

fmt.Println(“Hello, world!”)

fmt.Println(“Hello, world!”)

}

操作后变为:

package main

import “fmt”

func main()

{

fmt.Println(“Hello, world!”)

fmt.Println(“Hello, world!”)

fmt.Println(“Hello, world!”)

}

方法有两个:

第一个

移动光标到{}的其中一个;

直接按下>i{即可移动括号内全部内容。

第二个

移动到{后的第一条语句;

按下v进入可视模式;

使用方向键选定需要移动的行;

按下>即可完成移动;

超级联合

clip_image004

前面我们说过ddelete的缩写,此时可以和前面说过的w表示单词联合,所以dw就代表删除一个单词,而d$就是删除到行尾,d0就是删除到行首,dgg就是删除知道文件首,其他类推。

玩转VIM编辑器-vim附加特性

玩转VIM编辑器-vim附加特性

重复一个操作N

对于我们前面介绍的一些操作,我们可以单纯地加上一个数字,来重复操作N次,比如j表示下移一行,那么10j就是下移10行。

      还有一些重复执行的命令:

重复命令

描述

@@

重复前一个执行的宏

n

向同样的方向执行搜索

N

向相反的方向执行搜索

.

重复上一次的编辑命令

@

重复上一次的命令行操作

撤销和重复操作

单次撤销,直接使用字母u即可,如果想撤销N次操作,可以使用Nu

撤销全部操作,使用大写字母U即可。

      如果使用了u撤销操作,并且发现错误了,可以使用:red或者CTRL+R来撤销刚才做的编辑动作。

打开光标下对应的文件

      这个特性对于下述所示的情况相当有用。

l  测试配置文件中所给的文件名是有效的;

l  编辑一个文件的时候,想查看编辑文件中所包含的文件;

l  在编辑源代码的时候,参考include或者import的文件;

1.     直接打开:    gf

2.     打开一个新的窗口: CTRL+W f

3.     打开一个新的选项卡:    CTRL+W  gf

如果文件中所包含的文件并没有给出绝对路径,那么vim将在当前目录中搜索。

      在下述情况下,即使没有指出绝对路径,vim也能定位到文件的准确位置:

1.    C程序中的头文件;

2.    Perl程序中的Perl模块

使用传统方式编辑多个文件

      使用此种方法,可以在那一个vim会话中编译多个文件。

打开方法为:vim file1 file2 file3

如果已经处在vim编辑会话中,需要再打开一个文件,可以使用下述命令:

:e anotherfile

我们可以使用:ls来列出目前vim会话中的所有文件,比如:

:ls

  1 %a   “apue.h”                       line 1

  2 #    “passwd”                       line 1

  3      “lscpu”                        line 1

那么我们可以使用:e #N来打开第N个文件;

在两个文件中切换的方法为:  CTRL+^;

在多个文件中移动的方法:

使用命令:next:previous分别可以移动到下一个文件或者上一个文件。

自动保存文件

      如果在没有保存文件的时候,想切换到另一个编辑文件,会出现警告信息,提示先保存信息,可以设置自动保存选项:set autowrite,这样就可以直接切换各个文件或缓存。

      也可以使用:wall单个命令来写入所有的文件。

Vim中加密文件

使用:X来加密文件,下次编辑时就需要输入加密密码;

解密方法为:set key=然后保存文件就可以了。

加 密 的 局 限 性

Vim 采用的加密算法有弱点的。它对于防止那种偷窥者是绰绰有余了,但不足以防止一个手上有大量时间的密码专家。而且, 你应该知道交换文件是不加密的;所以当你在编辑文件时,拥有超级用户权限的人能够读取未经加密的文件文本。不让人们读到你的交换文件的一个方法就是不使用交换文件。

:setlocal noswapfile

由于没了交换文件,文件复原就不可能了。为了避免失去编辑的成果,要比平时更勤快地存盘你的文件。

保存和还原vim会话

      在我们编辑N个文件的时候,如果需要先做别的事情,在返回来编辑该会话,那么我们可以保存该会话,然后还原它,在这个过程中,诸如缓冲区、窗口大小、自定义选项、文件夹和当前目录等都会保存。

会话命令

描述

:mksession

在当前目录中创建一个默认的Session.vim

:mksession filename

保存会话为指定的文件名filename

$vim –S

打开当前目录中默认的会话

$vim –S filename

打开当前目录中指定的会话filename

:source Session.vim

导入会话中的所有设置

vim中执行Unix脚本命令

      vim中执行Unix命令cmd,使用:!cmd即可。比如显示:!date日期信息。

也可以将当前文件名作为一个参数传入到Unix命令中:

:!echo %

%代表当前文件名

:!echo %:p

%:p代表当前文件名的绝对路径

:!echo %:e

%:e代表当前文件的扩展名

使用vimdiff检查文件中的异同

      Unix中可以使用diff file1 file2来查看两个文件的异同(完全命令终端显示),但是vimdiff更加的直观、友好(不同颜色来友好地显示出文件异同)。

vimdiff命令

描述

vimdiff file1 file2

vim -d file1 file2

在一个垂直分割窗口中显示不同

vimdiff –o file1 file2

vim –d -o file1 file2

在一个水平分割窗口中显示不同

vim file1

:diffsplit file2

已经打开了一个文件,在打开另一个文件来比较异同水平分割

vim file1

:vert diffsplit file2

已经打开了一个文件,在打开另一个文件来比较异同垂直分割

[c

跳转到下一个修改处

]c

跳转到上一个修改处

vim映射命令

      如果需要重复地执行一个命令,可以使用vim的映射命令来实现。

比如:map :write :!cc % && ./a.out该映射命令在执行:write的时候就会编译当前文件并执行。

      前面我们提到过:w :up的区别,可以使用map :w :up;还有:map :q :confirm q

      使用:map可以显示所有定义的映射。

bash shell工作的像vim编辑器

set -o vi 表示编辑命令行用 vi 模式,默认状态是 vi 的 编辑状态,可以输入、修改,用 ESC 退出编辑状态后,可以用 h,l 来前进后退, j,k 来翻看历史命令,^光标到行首,$光标至行尾,dd 删除该行等等,和 vi 的用法是一样的。习惯用 vi 的人可以用 set -o vi 这种模式加快命令行编辑。

     此外,还有 set -o emacs,表示编辑命令行用 emacs 模式,不分编辑状态和控制状态。 可以直接输入,也可以用 [CTRL]-a 至行首,[CTRL]-e 至行尾,[CTRL]-k 删除光标处到末尾等等,这和 emacs 的编辑方式是一样的。这是默认模式,也是最常见和大多数人习惯的方式。

vim编辑器中的一些选项

选项

描述

:set nu

显示行号

:set ic

搜索时忽略大小写

:set ro

以只读模式打开

:set wm=n

最右端回卷最大值

:set ai

开启自动缩排功能

:set all

显示vim会话中的所有设置

:set list

显示所有不可视字符,比如^|表示tab$表示行尾

:set hlsearch

高亮显示匹配模式

:set incsearch

开启增量搜索模式,实时搜索

如果想关闭上述设置,可以使用:set no<OPTION>,例如不显示行号为:set nonu

默认寄存器和它们的用法

寄存器名称

描述

%

当前文件的名称

#

替换文件的名称

:

最近一次执行的命令

/

上一次的搜索模式

上一次使用的寄存器

      从寄存器中粘贴内容,执行下述命令

“<寄存器名称>p

比如如果“%p就会把当前文件名给粘贴到光标位置。

      关于寄存器,有以下几点需要注意:

1.    数字表示的只有从0910个寄存器;

2.    最近拷贝的存储在寄存器0

3.    最近删除的存储在寄存器1

vim目录操作

      我们可以使用vim作为一个文件管理器在文件系统中导航,并且可以进行一些操作。

      比如使用vim /可以看到:

clip_image002

      vim文件浏览器中,可以执行下述操作:

描述

<Enter>

打开光标对应的文件或文件夹

D

删除光标对应的文件

R

重命名光标对应的文件

X

执行光标对应的文件

o

打开一个水平分割窗口

      也可以在vim编辑器件中打开vim文件浏览器:

键值

描述

:Ex

vim文件浏览器打开当前目录

:Ex /etc

vim文件浏览器打开指定目录

:Sex

vim文件浏览器使用水平分割窗口打开当前目录

:Vex

vim文件浏览器使用垂直分割窗口打开当前目录

:Tex

vim文件浏览器在一个新的选项卡中打开当前目录

 

玩转VIM编辑器-程序员的一些技巧

玩转VIM编辑器程序员的一些技巧

代码语法高亮显示

      可以通过使用:syn on:syn off来开启或关闭代码语法高亮显示,效果如下:

 

clip_image002   clip_image004

 

巧妙的缩排

      对于特定的区域可以通过使用它CTRL+V来选择,然后通过>来整块向右移动,或者通过<向左移动。

      如果没有其他的设定,一般这种移动只能做一次,然后vim就进入正常模式,可以通过设定

:vnoremap < <gv

:vnoremap > >gv

来支持无限次移动,按ESC退出即可。

vim中访问man帮助页面

      vim编辑器中,如果想查询那个wordman页面,可以通过K来访问,当然,对于多个含义的,可以通过NK来访问不同章节的意义,其中N为数字,比如sleep,如果直接按K得到用户命令sleep的帮助页面,如果输入3K,那么将得到sleep函数的帮助页面。

定制man帮助页面的查找

      上面介绍的通过K来查询man帮助信息,如果对于perl程序员,可能更多的希望查询perldoc的信息,那么可以通过设定

:set keywordprg=perldoc -f

将会在按下K的时候,自动转移到perldoc而不使用man页面了。

跳转到变量定义处

      在光标位于某个变量的时候,可以通过gd来跳转到局部变量的定义处,通过gD来跳转到全局变量的定义处。

Tabular: Vim 中对齐文本

Vim 插件 Tabular 允许你在 Vim 中按等号、冒号、表格等来对齐文本,对于经常写代码的朋友来说,有 Tabular 将会非常方便。

clip_image006

如上图所示,假如我想让其中的两行按等号对齐,则将光标定位到有等号的那行,执行 :Tab /= 即可。

又如,若想将下面的

|1|2|

|one|two|

变成

| 1   | 2   |

| one | two |

可执行 :Tab /|

更详细的信息,我会单独拿出一部分来讲解这个plugin的使用。

使用它CTRL键来增加或者减小数字

      可以通过CTRL+A来使得光标对应的数字加1,或者CTRL+X来将光标对应的数字减1。当然,支持从0减小为负数的。

vim插入状态中执行vim命令

1.    处于vim的插入状态

2.    使用CTRL+O,这会使你暂时进入命令状态

3.    输入需要执行的命令

4.    命令执行完后,会自动返回到插入状态

查看当前文件细节

使用CTRL+G就可以看到类似

“***.c” [Modified] 338 lines –39%–  的基本信息,

更详细的信息可以通过g CTRL+G来查看,看到效果为

Col 52-59 of 55-62; Line 135 of 338; Word 379 of 816; Byte 3996 of 9506

关于vim的状态栏信息

      我们可以通过:set laststatus=2来使能查看行、列及百分比信息。

例如:

:set statusline=Filename:%t Line: %l Col: %c

看到的信息为:

Filename:shao.c Line: 140 Col: 4

又如下面的一些示例,可以打印一些比较感兴趣的内容:

:set statusline=%<%f %h%m%r%=%-14.(%l,%c%V%) %P

:set statusline=%<%f%h%m%r%=%b 0x%B %l,%c%V %P

:set statusline=%<%f%= [%1*%M%*%n%R%H] %-19(%3l,%02c%03V%)%O’%02b’

:set statusline=…%r%{VarExists(‘b:gzflag’,’ [GZ]’)}%h

      下面是一些状态栏中可以使用的关键变量,更详细的参考:help statusline

• F – 全路径Full path

• M – 修改标志显示为“+”“-“

• R – 只读标记,显示为“RO”.

• L –

• c –

• P – 显示窗口底部的百分比

大小写转换

控制键

描述

~

将光标指定的字符转换大小写

5~

更改接下来的5个字符

g~{移动键}

比如g~j将更改当前行和下面一行的大小写

g~~

将当前行全部更改大小写

gUU

将当前行全部更改为大写

guu

将当前行全部更改为小写

gUaw

将当前字字更改为大写

guaw

将当前字更改为小写

U

visual块全部改为大写

u

visual块全部改为小写

guG

从当前位置到文件结尾全部改为小写

gUG

从当前位置到文件结尾全部改为大写

拼写检查

拼写检查命令

描述

:set spell

启动拼写检查,将会高亮显示可能出现的错误

]s

跳到下一个拼写错误的地方

[s

跳到前一个拼写错误的地方

z=

对于拼写错误的建议

zg

将高亮显示错误的添加为有效单词

:echo &spelllang

显示拼写检查的语言

:set spelllang=code

设置拼写检测的语言

退出确认

      一般,如果我们忘记了保存修改的内容,而直接操作:q,将会提示No write since last change,我们可以通过:confirm q来提示是、否或取消当前操作。

提示为:

:confirm q

Save changes to “shao.c”?

[Y]es, (N)o, (C)ancel:

关于更新时间戳的问题

      一般我们执行:w的时候,不管有没有对文件内容有所操作,都会将时间戳更新,如果只是希望在更改了文件内容时,才更新时间戳,可以使用:up来操作。

制表符和空格键

命令

描述

:set expandtab

tab键自动转为空格键,一般是8个空格

:set tabstop=4

tab转换为4个空格

:retab

将文件中所有的tab转换为空格

:set shiftwidth=4

指定缩进的空格数目

:set ai

自动缩进,使用它^D可以向左缩进

 

玩转VIM编辑器-文本操作

玩转VIM编辑器文本操作

插入和添加文本

描述

i

在当前位置插入文本

I

在当前行首插入文本

o

在当前行的下一行新建一行并插入文本

O

在当前行的上一行新建一行并插入文本

:r filename

在当前行的下一行开始插入filename中的内容

:r !command

在当前行的下一行插入command的输出信息

a

在当前光标后添加文本

A

在当前行末添加文本

替换文本

描述

rc

使用c替换当前字符

R

命令与r相同,用于替换文本,不同在于,按下R后会进入覆盖模式,输入的字符将逐一覆盖屏幕上的字符,直到ESC为止。

s

删除当前光标字符,然后插入文本

S

删除整行,并插入文本

4s

删除当前4个光标字符,然后插入文本

4S

删除4行,并插入文本

cc

S

C

将从光标开始到行末的字符删除,并开始插入文本

连接行与行

可以使用J来将行与行进行连接,中间只有一个空格隔开。

复制一个字符、单词或行

键值

描述

yc

复制单个字符

yw

复制单个字

yl

向下复制一行,也可以yk向上复制

y<mark name>

复制一个书签行

y’<mark name>

复制到一个书签的位置

粘贴

可以使用p来粘贴到光标所在的下一行,或者P来粘贴到光标所在的上一行。

      我们可以通过:reg来查看寄存器中的一些操作量,可以使用”np来粘贴第n个寄存器的内容,其中n:reg中的第一列。

删除单个字符、字或者行

键值

描述

x

删除光标当前字符

dw

删除当前字

dj

删除当前行和下一行

从剪切板粘贴内容

      在普通模式下,可以使用”*p来插入剪贴板的内容。

从当前文件复制内容到剪贴板

复制到粘贴板

描述

:%p

将整个文件复制到粘贴板

:y

复制当前行到粘贴板

:N,My

复制指定的NM行至粘贴板

将文件的部分内容写到另一个文件

      可以使用CRTL+V块选择来指定文件内容,然后使用:w newfilename,来将内容写到新的文件;或者使用:5,10w newfilename将第510行写到新的文件。

交换单词

      如果将as写成了sa,快速交换次序的方法为执行xp,解释为x为剪切当前字符,p为粘贴。可以测试一下。所以xp的意思就是转置。

强大的点.

      Dot.)的含义为重复上一次对文件内容有影响的命令,注意是有修改的命令,所以单纯的移动是不重复的。

可视模式命令

可视模式命令

可视模式类型

描述

v

选择字符,从当前字符开始

V

选择字符,从当前字符所在的行开始

CTRL+V

块选择

 

可视模式命令

描述

<ESC>

退出可视模式

d

删除高亮选择的部分

D

删除高亮部分所在的行

y

拷贝高亮部分文本

Y

拷贝高亮部分所在的行

c

删除高亮文本并且进入插入模式

C

删除高亮文本所在的行并且进入插入模式

使用:g来编辑

示例

描述

:g/^$/d

删除所有的空白行

:g/^s*$/d

删除所有的空白行和由空格组成的行

:g/^$/,/./-j

将多个空白行改变为单个空白行

:g/pattern/d

删除带有指定pattern的行

:g/pattern/ . w>>filename

将带有指定pattern的行写入文件filename

:g/^/m0

反转整个文件

:g/^s*PATTERN

/exe “norm! I/* <ESC>A */<ESC>”

意义添加匹配PATTERN的行,为c风格的注释

上述的:g可以使用:g!或者:v来做相反的操作,例如:g!/^$/d就是删除所有非空白的行。

拷贝文本行到命名缓冲区

      将文本拷贝到命名缓冲区,后面可以直接通过该缓冲区使用。有效的缓冲区名字为从az26个字母。

命令

描述

“ayy

拷贝当前行到缓冲区a

“a5yy

拷贝5行到缓冲区a

“ap

光标后粘贴缓冲区a的内容

“aP

光标前粘贴缓冲区a的内容

将插入的文本当作正常命令

      如果在插入模式下输入了命令,那么可以按F2来将输入文本转为命令执行。当然这个需要在vimrc中定义inoremap <F2> <ESC>u@.  其中最后有个点号

缩写和非缩写

      如果经常需要输入邮箱、住址或这单位,这个功能就比较使用。例如the People’s Republic of China,那么我们只需要:addr CHINA  the People’s Republic of China,以后在输入CHINA的时候就会自动转为the People’s Republic of China,又如:addr EMAIL thisismyemail@gmail.com,那么我们在输入EMAIL的时候,就会自动转为thisismyemail@gmail.com

      其中的addr也可以使用iabbrev替代。

      使用:noabbr CHINA就可以取消该缩写。

宏的使用

      宏就是记录我们的操作动作,后续的可以按照我们的设定进行工作。

      步骤如下:

1.    按下q开始记录,后面跟上一个小写的字母,比如a作为宏的名字;

2.    vim中进行一些操作,这些宏a都会记录;

3.    按下q停止记录;

4.    使用宏,可以通过@a来回放宏a

5.    如果想执行多次操作,可以使用:N@a,其中N为次数。

文件内容排序

:sort会对文件的所有内容进行排序,如果需要对特定的行进行排序,可以使用块选择,然后在执行sort操作。

:sort选项

描述

:sort

升序排列

:sort!

降序排列

:sort i

忽略大小写排序

:sort u

移除掉重复的行

:sort! ui

也可以将上述几种进行结合操作

恢复删除的文本

      如果误删除了一些文本,可以恢复最近9个操作过的文本。因为他们都保存在编号的缓冲区中,最后一次删除的内容保存在缓冲区1,倒数第二次的则保存在缓冲区2……要恢复删除操作,先输入(双引号),接着指定缓冲区编号,在使用放置命令。

恢复误操作

描述

“1p

恢复最近一次的误操作

“2p

恢复最近倒数第二次的误操作

“3p

恢复最近倒数第三次的误操作

      如果你不清楚删除的内容,可以查看9个删除的缓冲区内容。也可以使用下述命令,直到你找到正确的那个(如果在恢复p一次后利用重复命令(.)做恢复,缓冲区的编号会自动增加,再加上用u撤销恢复,即可用下例搜索变化的缓冲区:)

“1pu.u.u.u.u.u.

删除文件时发生的问题

1.    使用u来撤销上一个命令,但这只适用于尚未下达其他命令的时候,因为u只会撤销最近一个命令;

2.    可以使用p命令,因为vi会将最近9次的删除动作保存在9个编号的删除缓冲区中。

3.    其实vim支持“无限”恢复的,因此挽救失误因此简单多了。

重复或撤销上一个命令

每一个编辑命令均存储到一个临时的缓冲区,直到发出下一个命令为止。

要想重复相同的编辑命令时,可以使用重复命令,句号(.,以节省时间。

可以使用u来撤销上一个命令;

使用U会撤销所有对同一行的编辑动作,只要光标还在这一行即可,一旦你移到别的行,就不能使用U了。

VIM让我们用CTRL+R来重做一次撤销操作,即撤销所作的撤销操作。

为一些文件自动添加一些东西

      Vim中有40多个自动命令的触发事件。例如下面几个:

事件

描述

BufNewFile

开始编辑一个不存在的文件

FileReadPre

在读取一个文件前使用:read命令

BufWritePre

将整个缓存写入一个文件

FileWritePre

将部分缓存写入一个文件

BufDelete

在一个缓存列表中删除一个缓存

BufWipeout

清空整个缓存前

BufNew

创建一个新的缓存后

BufEnter

进入一个缓存后

BufLeave

离开到另一个缓存前

SwapExists

检测一个存在的swap文件

      很多开发者希望在编写程序的时候就把一些必须的东西直接填写在文件中,比如打开文件就希望是如下:

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.

* File Name : 1.c

* Purpose :

* Creation Date : 22-12-2008

* Last Modified : Mon 22 Dec 2008 10:36:49 PM PST

* Created By :

_._._._._._._._._._._._._._._._._._._._._.*/

完成这样的操作步骤如下所示:

首先:创建一个临时的文件,比如c_header.txt

:insert

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.

* File Name :

* Purpose :

* Creation Date :

* Last Modified :

* Created By :

 _._._._._._._._._._._._._._._._._._._._._.*/

 .

注意文件刚开始的:insert和最后的点号.

然后:将自动化的命令添加到vimrc文件中:

autocmd bufnewfile *.c so /home/name/c_header.txt

autocmd bufnewfile *.c exe “1,” . 10 . “g/File Name :.*/s//File Name : ” .expand(“%”)

autocmd bufnewfile *.c exe “1,” . 10 . “g/Creation Date :.*/s//Creation Date : ” .strftime(“%d-%m-%Y”)

autocmd Bufwritepre,filewritepre *.c execute “normal ma”

autocmd Bufwritepre,filewritepre *.c exe “1,” . 10 . “g/Last Modified :.*/s/Last Modified :.*/Last Modified : ” .strftime(“%c”)

autocmd bufwritepost,filewritepost *.c execute “normal `a”

最后:可以创建一个新的.c文件进行测试

可以看到刚开始只会把创建时间等信息填写上,在保存文件后会自动把上一次编辑时间给填写上。

      可以通过:version来查看vim的版本以及支持的一些特性。

更改大小写

波浪号~可以将小写字母改成大写的,或者将大写字母改成小写的。

移动到特定的行

若想移动到特定行,可以使用G命令,只按G将移动到文件的结尾,4G则移动到第4行。

文本创建与操纵命令

编辑动作

命令

在光标所在位置插入文本

i

在一行的开头插入文本

I

在光标所在位置附加文本

a

在一行的最后附加文本

A

在光标下一行打开新行

o

在光标上一行打开新行

O

删除一行并替换文本

S

用新文本覆盖现有的文本

R

合并当前这一行与下一行

J

切换当前字符的大小写

~

重复上一次动作

.

撤销上一次动作

u

将一整行恢复到原来的状态

U

编辑命令

文本对象

更改

删除

复制

一个单词

cw

dw

yw

两个单词,不包括标点符号

2cWc2W

2dWd2W

2yW或者y2W

后退三个单词

3cbc3b

3dbd3b

3yby3b

一整行

cc

dd

yyy

到一行的结尾

Cc$

Dd$

y$

到一行的开头

c0

d0

y0

单个字符

r

Xx

y1

五个字符

5s

5x

5y1