用途说明
vi是Linux/Unix中最常用的文本编辑器,它是全屏幕的编辑器,类似DOS/Windows下的edit程序,但它的使用方式与edit很不一 样。vi是“Visual Interface”的缩略词,来源于另外一个文本编辑器ex的命令visual。vi是一种模式编辑器。不同的按键可以更改不同的“模式 (mode)”;比如说:在“插入模式(insert mode)”下,输入的文本会直接被插入到文档;当按下“退出键(ESC)”,“插入模式”就会更改为“命令模式(command mode)”,并且光标的移动和功能的编辑都由字母来响应,例如:“j”用来移动光标到下一行;“k”用来移动光标到上一行,“x”可以删除当前光标处的 字符,“i”可以返回到“插入模式”(也可以使用方向键)。在“命令模式”下,敲入的键(字母)并不会插入到文档,这使得新接触vi的用户很迷惑。
在Linux下,我们在使用vi时实际使用的是vim(ViIMproved),vim是一个与vi向上兼容的文本编辑器(Vim is a text editor that is upwardscompatible to Vi)。说实话,vi中的命令实在太多,无法全部掌握,本文只列举了一些常用的,想对vi/vim有更多了解的话,可以参考后面的相关资料部分。
常用参数
格式:vi <file>
使用vi编辑<file>指定的文件。
格式:vi -R<file>
格式:view <file>
用vi打开<file>指定的文件,但不能编辑,即只读模式。要达到类似的效果也可以使用more/less。
格式:vi <file1><file2>
格式:vi <file1><file2> <file3>
用vi打开多个文件编辑。如果在编辑完第一个文件之后按:q退出,vi就会提示“E173:还有 2 个文件未编辑”,可以使用:n继续编辑下一个文件。
格式:vi +n<file>
用vi编辑<file>指定的文件,并且将光标定位到第n行,从1开始计数。如:vi+2 1.txt。
格式:vi +/pattern<file>
用vi编辑<file>指定的文件,并且将光标定位到符合pattern模式的行。如:vi +/world 1.txt。
下面对vi下常用的编辑命令做一个小结:注意大小写,效果是不一样的。
ESC退出插入模式;有时候为了确认不是在插入模式,可多按ESC键,因为下面的命令都是在命令模式执行的。
小写i 进入插入模式,插入点在当前光标之前;
小写a进入插入模式,插入点在当前光标之后;
大写A进入插入模式,插入点在当前行末尾;
小写o进入插入模式,插入点在当前行后,新增一行;
大写O进入插入模式,插入点在当前行前,新增一行;
下面是常用的删除命令:
小写x 删除当前光标后的字符;
大写X 删除当前光标前得字符;
小写dw 删除一个单词;
小写dd 删除一行;
小写d$ 删除至行尾;
下面是常用的移动光标的命令:
上下左右箭头这个你懂的;还有hjkl这四个字符分别是左下上右四个方向移动光标,不常用;
数字0 定位到行首;
美元符$ 定位到行尾;
下面几个是常用的搜索命令:
/pattern查找pattern匹配的位置
n 定位到下一个匹配的位置
N 定位到前一个匹配的位置
?pattern与/pattern相反,它是反向查找的,同样的n和N的定位方向也是相反的。
注意pattern为正则表达式,但与java里面的有些不一样。比如()不是元字符,\(\)才是。
还有一些常用的行命令,即冒号跟上一些字符然后回车,如:
:0 定位到第一行;
:$ 定位到最后一行;
:n 定位到n行,其中n为任意数字;
:.=显示当前行号;很多时候都需要确定当前的行号;
下面是常用的替换命令:
:%s/pattern/replace/g将符合pattern模式的所有字符串替换为replace,如 :%s/123/456/g
:n,m/pattern/replace/g将符合pattern模式的所有字符串替换为replace,但只对从n到m行之间的替换。
注意%s相当于1,$,即从第1到最后一行。
保存和退出命令:
:w 保存
:wq或:x 保存并退出
:q! 不保存,退出
使用示例
示例一 RHEL5.5下vi命令不支持语法高亮显示的问题
在安装了RHEL5.5后,我发现一个问题,在使用vi编辑c代码文件时,不支持语法高亮显示,开始时以为是没有安装vim-enhanced软件包,一查之后发现这个猜测错了,如下所示:
[root@jfht ~]# rpm -qa | grep vim
vim-minimal-7.0.109-6.el5
vim-common-7.0.109-6.el5
vim-enhanced-7.0.109-6.el5
[root@jfht ~]#
这个问题让我迷惑了很久,后来发现在这个版本下vi和vim两个程序的表现不一样,直接用vim命令就没有问题了,在/etc/profile的尾部增加了一个别名(alias)就可以使用vi命令获得同样的效果了,如下所示:
aliasvi="vim"
保存/etc/profile重新登录,就会发现vi可以支持语法高亮显示了。
示例二 语法高亮显示配置文件
vim支持语法高亮显示,每种语言它定义了语法显示样式文件,通常在/usr /share/vim/vim70下(注意目录中的vim版本)找到filetype.vim,其中syntax目录下有很多.vim文件,它定义了各种 语言的语法高亮显示规则。你也可以增加自己的语法规则,当然需要熟悉其中的规则。
[root@web ~]# less /usr/share/vim/vim70/filetype.vim
" Vim supportfile to detect file types
"
"Maintainer: Bram Moolenaar <Bram@vim.org>
" LastChange: 2006 Aug 25
" Listen verycarefully, I will say this only once
ifexists("did_load_filetypes")
finish
endif
letdid_load_filetypes = 1
" Linecontinuation is used here, remove 'C' from 'cpoptions'
let s:cpo_save =&cpo
set cpo&vim
augroupfiletypedetect
" Ignoredextensions
ifexists("*fnameescape")
auBufNewFile,BufRead ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.rpmsave,?\+.rpmnew
\ exe "doau filetypedetect BufRead " .fnameescape(expand("<afile>:r"))
auBufNewFile,BufRead *~
\ let s:name = expand("<afile>") |
\ let s:short = substitute(s:name, '\~$', '', '') |
\ if s:name != s:short && s:short != "" |
\ exe "doau filetypedetect BufRead " .fnameescape(s:short) |
\ endif |
\ unlet s:name s:short
auBufNewFile,BufRead ?\+.in
\ if expand("<afile>:t") != "configure.in" |
\ exe "doau filetypedetect BufRead " .fnameescape(expand("<afile>:r")) |
\ endif
elseif &verbose> 0
echomsg"Warning: some filetypes will not be recognized because this version ofVim does not have fnameescape()"
endif
" Pattern usedto match file names which should not be inspected.
" Currentlyfinds compressed files.
if!exists("g:ft_ignore_pat")
letg:ft_ignore_pat = '\.\(Z\|gz\|bz2\|zip\|tgz\)$'
[root@web ~]#
[root@web ~]# less /usr/share/vim/vim70/syntax/c.vim
" Vim syntaxfile
"Language: C
"Maintainer: Bram Moolenaar <Bram@vim.org>
" LastChange: 2006 May 01
" Quit when a(custom) syntax file was already loaded
ifexists("b:current_syntax")
finish
endif
" A bunch ofuseful C keywords
synkeyword cStatement gotobreak return continue asm
synkeyword cLabel case default
synkeyword cConditional if else switch
synkeyword cRepeat while for do
synkeyword cTodo containedTODO FIXME XXX
" cCommentGroupallows adding matches for special things in comments
syncluster cCommentGroup contains=cTodo
" String andCharacter constants
" Highlightspecial characters (those which have a backslash) differently
synmatch cSpecial display contained"\\\(x\x\+\|\o\{1,3}\|.\|$\)"
if!exists("c_no_utf")
synmatch cSpecial display contained"\\\(u\x\{4}\|U\x\{8}\)"
endif
ifexists("c_no_cformat")
synregion cString start=+L\="+skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell
"cCppString: same as cString, but ends at end of line
synregion cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$'contains=cSpecial,@Spell
else
if!exists("c_no_c99") " ISO C99
syn match cFormat display "%\(\d\+\$\)\=[-+'#0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn]\|\[\^\=.[^]]*\]\)"contained
else
syn match cFormat display "%\(\d\+\$\)\=[-+'#0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([bdiuoxXDOUfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)"contained
endif
synmatch cFormat display "%%"contained
[root@web ~]#
示例三 在vi中进行字符串替换(2011.08.04)
在C++中,我们常用std::cerr和std::cout打印一些调试信息,在调试好程序之后又要将其去掉。怎么做才比较快?在vi中可以通过下面的命令来实现:
在std::cerr前面加上注释:
:%s/std::cerr/\/\/std::cerr/g
在std::cout前面加上注释:
:%s/std::cout/\/\/std::cout/g
要注意,/是个特殊字符,它被用作搜索范围、源字符串、目标字符串、选项之间的分隔符,因此当/作为目标字符串的一部分时,必须转义。