文本编辑器vim/vi用法完全解读
vi是UNIX/Linux系统下最强大的文本编辑器(另一个是Emacs),其命令较多,完全基于键盘操作,而当下流行的各种Linux版本基本上都内置安装了vim,vim可以看作是vi的增强型版本,两者用法大致相同。习惯了使用图形化文本编辑器的同学学习vi编辑器比较费劲、难以适应,为了方便大家学习,我在这里着重介绍一下vi的核心用法。
1.启动vim
vim [-C] [-rR] [file…]
- 选项’-C’,将以兼容模式启动,使Vim像vi一样打开文本文件;
- 选项“-r”可以恢复上次保存失败的文件,若后面不跟文件名‘file’将显示所有可用恢复数据的文件;
- 选项“-R"以只读模式打开文本文件;
- file代表要编辑的文件名称,若不存在此文件,vim则会新建一个新的空文件‘file’,若无此file参数,vim将会在退出时,提醒输入当前的文件名以保存文件。
2.命令模式和输入模式
-
编辑缓冲区
在使用vi时,存放数据的存储区域称为编辑缓冲区。编辑文件时处理的是编辑缓冲区的数据副本,只有在保存时才会将编辑后的数据写入原文件。 -
在vi中有命令、输入两种模式。
- 命令模式
所有键入的键都被解释成命令,如x就是删除一个字符的命令。 - 输入模式
键入的任何内容都被写入编辑缓冲区中,如键入”how are you",那么这11个字符被插入到编辑缓冲区中。
- 两种模式的切换
在命令模式中,可以用多种方式(如输入’i‘或“a”等)进入输入模式,而在输入模式中只需要按下<Esc>键即可退出当前模式,进入到命令模式中。 - 了解当前所处模式
在输入模式时,vim在屏幕左下角显示以下提醒:
- - INSERT - -
3.退出vi
退出前必须在命令模式中输入一条退出命令,若在输入械中,则就先切换到命令模式中再输入退出命令。
- 退出并保存
- <Shift>+ZZ
按下并保持<Shift>,再按两次Z键,即可退出并保存当前文件。 - :wq<Return>
输入字符“:wq”,然后再按回车键<Return>,即可退出并保存当前文件。
- 退出而不保存
:q!<Return>
输入字符“:q!”,然后再按回车键<Return>,即可退出vim,但不保存当前文件。
4.vi与ex命令
- vi命令
vi命令较短,以单字母或双字母的形式出现。如光标前称一个单词用“w”命令,删除当前行可用“dd”命令。在命令模式下直接键入这命令字符即可,不用输入回车键<Return>,且键入命令时不加回显。 - ex命令
ex命令较长、更为复杂,在键入过程中它们会回显在命令行上,所有的ex命令都以冒号“:”开头,最后还要按下回车键<Return>(回车字符不显示),如将"hello"修改成“hi",则有如下命令
:/hello/hi/g<Return>
输入模式下可能输入一些错误的字符,你会想对其中的个别字符进行修正。
键 | 说明 |
---|---|
<Backspace>(回退键)或<Delete>(删除键) | 删除键入的最后一个字符 |
^W | 删除键入的最后一个单词 |
^X或^U | 删除整行 |
注:“^<KEY>”表示按下Ctl+KEY键,如“^U”表示同时按下“Ctl”和“U”键。
5.移动光标
- 单字符长度的移动
键 | 移动说明 |
---|---|
h或<Left>或<Backspace> | 光标左移一个字符长度的位置 |
l或<Right>或<Space> | 光标右移一个字符长度的位置 |
j或<Down> | 光标下移一个位置 |
k或<UP> | 光标上移一个位置 |
- 单词长度的移动
键 | 移动说明 |
---|---|
w | 光标移动到下一个单词的词首 |
W | 以忽略标点的方式,光标移动到下一个单词的词首 |
e | 光标移动到下一个单词的词尾 |
E | 以忽略标点的方式,光标移动到下一个单词的词尾 |
b | 光标移动到上一个单词的词首 |
B | 以忽略标点的方式,光标移动到上一个单词的词首 |
- 行距离的移动
键 | 移动说明 |
---|---|
- | 光标移动到上一行的开头 |
+或<Return> | 光标移动到下一行的开头 |
0(数字,非字母“o") | 光标移动到当前行的开头 |
$ | 光标移动到当前行的末尾 |
^ | 光标移动到当前行的第一个非空格、非制表符的的字符上 |
- 较大范围的移动
键 | 移动说明 |
---|---|
) | 向前移动到下一个句子 |
( | 向后移动到上一个句子 |
} | 向前移动到下一个段落 |
{ | 向后移动到上一个段落 |
H | 光标移动到屏幕的顶部 |
M | 光标移动到屏幕的正中间行 |
L | 光标移动到屏幕的最后一行 |
^D | 向下移动半屏 |
^U | 向上移动半屏 |
^F | 向前移动到下一屏 |
^B | 向后移动到上一屏 |
注:为增强光标移动命令的功能,可在命令前键入一个数字不重复执行光标移动命令如:
10w
光标 可以向后移动10个单词长度的距离,但数字之后不能有空格
6.跳转
- 跳转至指定行
命令 | 说明 |
---|---|
1G或gg 或:1 | 跳转到第一行 |
G | 跳转至末尾行 |
nG | 跳转到第n行 |
:n | 跳转到第n行 |
: $ | 跳转到最后一行 |
注:命令":set number"可设置显示行号
- 跳转至以前位置
- ``(两个反引号) , 跳转到前一位置。
- 另外可用m<KEY>来标记当前行,如
mb
为了跳转到一个标记行可以键入`(反引号)或’(单引号),后面再跟被标记的<KEY>如
`b 或 'b
7.搜索
ex命令 | 说明 |
---|---|
/xxxx<Return> | 向下查找字符”xxxx“ |
?xxxx<Return> | 向上查找字符”xxxx“ |
结合全正则表达式,搜索命令会变得更灵活方便。
元字符 | 说明 |
---|---|
. | 匹配除新行字符之外的任意单个字符 |
^ | 锚:匹配行的开头 |
$ | 锚:匹配行的末尾 |
\< | 锚:匹配单词的开头 |
\> | 锚:匹配单词的末尾 |
[list] | 字符类:匹配list中的任意字符 |
[^list] | 字符类:匹配不在list中的任意字符 |
\ | 引用:字面意义上解析元字符 |
注:重复上次的搜索并再次跳转,可以直接键入/或?,再按回车键<Return>。
而一旦使用了/或?,就可以按照此模式继续搜索上一个或下一个匹配字符。n命令采取和原始命令相同的方向进行搜索,N(大写的n)命令以相反方向搜索(此时按下N或n不需要按回车键<Return>)。
8.插入文本
要想插入文本,必须从命令模式进行输入模式,而进入输入模式有12种之多,每种进入插入模式的命令的插入位置都不大相同。
命令 | 插入说明 |
---|---|
i | 在当前光标位置前插入数据 |
a | 在当前光标位置后插入数据 |
I | 在光标当前行开头插入数据 |
A | 在光标当前行末尾插入数据 |
o | 在当前行下面插入一行 |
O | 在当前行上面插入一行 |
注
1.若当前行是" Who are you?",且此时光标在W上,在输入acc<Esc>后,此行将变成
Wccho are you?
2.^V<key>可以输入原本不可见的控制字符,如键入^V^H,vi则会显示出^H字符。
9.修改文本
- vi命令
命令 | 说明 |
---|---|
rx | 用一个新字符x替换光标处的那个单字符,且替换后还是处于命令模式中 |
Rxxxxx | 用一个字符串xxxxx从光标处开始逐个替换与xxxxx等长的字符 |
sxxxxx | 用一个字符串xxxxx替换光标处的那个字符 |
Cxxxxx | 用一个字符串xxxxx替换从当前光标位置至此行末尾的所有字符 |
Sxxxxx或ccxxxxx | 用字符串xxxxx替换当前行的整行内容 |
c move xxxxx | 以插入方式从当前光标处到move给出的位置处的所有字符替换成xxxxx |
注:
1.修改文本的命令都会使(若当前模式就是命令模式的话)命令模式切换成输入模式(r命令例外),只有再次键入<Esc>才会切换回命令模式
2.在c后面再跟一个移动光标的命令,也会进入输入模式即"c move"。但此时键入的新内容将替换从光标当前位置到由移动命令move所指定位置之间的所在字符。如当前行是:
Would you want to go home ?
当前光标在g上时,如果你键入了c2wbuy bag,那么当此行将变成
Would you want to buy bag ?
“c2w”表示当前光标处后的两个单词将被替换成一些预期的新字符。
10.替换文本
- ex命令
命令 | 说明 |
---|---|
: s/pattern/replace/ | 当前行内,用replace替换被pattern匹配的内容 |
:line s/pattern/replace/ | 在第line行内,用replace替换被pattern匹配的内容 |
:line1,line2 s/pattern/replace/ | 在第line1至line2行范围之间,用replace替换被pattern匹配的内容 |
:1,$s/pattern/replace/ | 在所有行(全缓冲区)范围之间,用replace替换被pattern匹配的内容 |
:%s/pattern/replace/ | 在所有行(全缓冲区)范围之间,用replace替换被pattern匹配的内容 |
注:
- ": s/pattern/replace/“只是替换行的第一个模式匹配项,若要替换该行 的所有匹配项,愚昧在命令的末尾加上字母g(global的缩写,表示全局)。
如,为了将当前行所有的”UNIX"都替换为“Linux”,可使用命令:
: s/UNIX/Linux/g- 若希望在改变之前先要确认,则可在 ": s/pattern/replace/"人与人之间的末尾加上字母c(confirm的缩写,表示确认),可输入
: s/UNIX/Linux/c- 另外g和c也可以组合一起使用,如
: s/UNIX/Linux/cg
11.删除文本
- vi命令
命令 | 说明 |
---|---|
x | 删除当前光标处的字符 |
X | 删除光标左边的字符 |
D | 删除当前光标处至本行末尾的字符 |
d ‘move’ | 删除当前光标至具体move命令所给位置的字符 |
dd | 删除当前行 |
- ex命令
命令 | 说明 |
---|---|
:line d | 删除第line行 |
:line1,line2 d | 删除第line1至第line2行 |
:line, . d | 删除第line至当前行的文本内容(点号‘.’表示当前光标所在行) |
注:
- "d mover"命令非常强大,如dw可删除一个单词,db可向后删除一个单词,d5)可删除5个句子。
- "%“表示缓冲区所有行,”.“表示光标所在的当前行,”$"表示缓冲区的最后一行。
12.恢复和撤销改变
vi命令 | 说明 |
---|---|
u | 撤销上一命令对编辑缓冲区的修改 |
U | 恢复当前行(撤销自移动到当前行起所做的所有修改) |
. | 重复上一命令对编辑缓冲区的修改 |
13.恢复删除
每当删除一行或多选文本时,vi都将删除内容保存在一个叫编号缓冲区的特殊存储区中。vi中共在9 个这样的缓冲区,编号从1至9。在任何进修,都可以将一个编号缓冲区中的内容插入到编辑缓冲区中。格式是,先键入一个"(双引号),后面紧跟着缓冲区的编号,再后跟一个p或P命令(p命令在当前行的下面插入,P命令在当前行的上面插入)。
如命令
"3p
可将编号缓冲区#3的内容插入到当前行的下面。
常用"1pu"2pu"3pu . . .或"1pu.u.u . . .来恢复并插入多次删除的内容
注:
编号缓冲区只存储删除的行,而不是行的一部分或单个字符。
14.移动文本
vi会在无名缓冲区上保存上一次删除内容的副本。在任何时候都可用p或P命令将无名缓冲区的内容复制到编辑缓冲区。
vi命令 | 说明 |
---|---|
p | 复制上一次删除的内容,插入到光标后面 |
P | 复制上一次删除的内容,插入到光标前面 |
xp | 调换两个字符 |
deep | 调换两个单词 |
ddp | 调换两行 |
15.复制文本
从一个位置向另一位置复制文本有3个步骤,第一,使用y、yy(等同于Y)或Y命令将文本由编辑缓冲区复制到无名缓冲缓冲区,但不删除原始文本;第二步,将光标移动到预期要插入文本的目标位置;第三步,使用p或P命令执行插入。
我们通常把在不删除文本的情况下将文本复制到无名缓冲区的操作称为接出,而y、yy工作方式与d、dd的工作方式相同,如
yw 接出1 个单词
y2) 接出2w个句子
yy 接出1行
9yy 接出9行
然后移动光标到要插入的位置,再使用p(粘到目标后)或P(粘到目标前)粘贴出这些接出的内容。
16.改变字母的大小写
~(波浪号)vi命令可使光标处字母改变大小写(原来大写的字母变成小写,原来小定的字母变成大写),并使光标向前称一个位置。一直重复地键入~可以连续改变文本的大小写,而键入n~会将光标处的n个字符的大小写都给改变了。
17.设置和显示选项
- 设置选项
vi支持许多的选项,而当vi启动时,每个选项都被赋为默认值。若要改变vi当前的某方面设置,可以用ex风格的:set 命令设置合适的选项值。此命令有两种形式。
:set [no] option …
:set option[ = value] …
开头 | 缩写 | 默认值 | 含义 |
---|---|---|---|
autoindent | ai | off | 和shift width相差,缩进以匹配上下行 |
autowrite | aw | off | 若文本已修改,则在切换文件前保存 |
errbells | eb | off | 当显示错误消息时发出嘀嘀声 |
exrc | ex | off | 在当前目录中查找初始化文件 |
ignorecase | ic | off | 搜索过程中忽略大小写 |
list | —— | off | 将制表符显示为^I,将行的结束显示为$ |
number | nu | off | 显示行号 |
readonly | ro | off | 只读,不能修改编辑缓冲区的内容 |
showmatch | sm | off | 输入模式:显示匹配的()、{}或[] |
showmode | smd | off | 当进入输入模式时显示一个提醒 |
wrapscan | ws | off | 搜索过程中,环绕到文本的开头/末尾继续搜索 |
writeany | wa | off | 允许一需要的重载!就可以写入任何文件 |
lines | —— | 24 | 文本的行数 |
shiftwidth | sw | 8 | autoindent使用的空格数量 |
tabstop | ts | 8 | 制表符间距 |
wrapmargin | wm | 0 | 自动换行的页边距 |
大多数据的选项都有缩写,为了方便快捷,可使用缩写代替全称。如以下命令是等价的。
:set showmod nonumber tabstop=4
:set smd nonu ts=4
- 显示选项
为了显示一个或多个选项的值,可使用:set命令的一种变体。语法如下:
:set [ option[?] … ] [all]
例如,
:set all 可以显示所所有的选项值,
:set number? showmod? wrapmargin? 将同时显示行号标记是否开启、插入模式提醒是否开启以及页边距是多少。
18.分隔与连接行
vi命令 | 说明 |
---|---|
r<Return> | 在空格处键入r,再键入回车符,当前行将在此空格处分裂为两行 |
J<Return> | 在当前行键入J和回车符,当前行与下一行将合并为一行 |
19.复制与移动行
ex命令 | 说明 |
---|---|
:x,[y]coz | 源行x(至y)复制到目标行z下面 |
:x,[y]mz | 源行x(至y)移动到目标行z下面 |
例:复制第5行,插入到11行下面
:5co11
移动第7至9行,插入到15行下面
:7,9m15
首行到当前行之间的内容移动到编辑缓冲区的末尾
:1,.m$
当前行到末行之间的内容移动到编辑缓冲区的开头(行0代表缓冲区的开头)
:.,$m0
20.输入shell命令
命令 | 说明 |
---|---|
:! shell-cmd | 暂停vi,让shell执行shell-cmd命令,shell命令 执行结束后,控制将返回给vi |
:! ! | 再次执行上次的shell命令 |
:! sh | 启动一个新的默认shell,在使用完这个shell之后,可以按^D键或输入exit来停止这个shell,重新回到vi中 |
:! shell-name | 启动一个新的指定shell-name的shell |
21.将文件中的数据或 shell命令的输出插入到编辑缓冲区中
-
文件内容插入
:r命令可把文件的内容加入到编辑缓冲区,具体语法是
:[line]r file
例:将readme.txt文件内容插入到编辑缓冲区17行之后
:17r readme.txt
将readme.txt文件内容插入到编辑缓冲区的开头
:0r readme.txt
将readme.txt文件内容插入到编辑缓冲区的末尾
:$r readme.txt
将readme.txt文件内容插入到当前行之后(省略行号)
:r readme.txt -
shell输出插入
ex命令 | 说明 |
---|---|
nr file | 在第n行后插入文件file的内容 |
r file | 在当前行后插入文件file的内容 |
n r ! shell-cmd | 在第n行后插入shell-cmd的输出 |
r ! shell-cmd | 在当前行后插入shell-cmd的输出 |
22.将数据写入文件
ex命令 | 说明 |
---|---|
:w | 将数据写入原始文件 |
:w file | 将数据写入到新文件file中 |
:w! file | 覆盖一个已有的文件file中 |
:w>> file | 将数据追加到指定的文件file中 |
23.切换到一个新文件
在编辑一个文件时,临时决定到编辑另一个文件,其实不用退出vi就可以编辑其他文件,可用:e命令 ,后面跟一个新的文件名即可,语法:
:e file
而在编辑新文件时,编辑缓冲区的原有内容将丢失,因此此时vi会提醒你保存对原来文件修改的保存,不保存不能切换到新文件的编辑,此时可用:w保存数据。如果要忽略这种保护,可用:e!
ex命令 | 说明 |
---|---|
e file | 编辑新的文件file |
e! | 重新编辑当前文件file,忽略自动检查(丢弃所有的修改) |
e! file | 编辑指定的新文件file,忽略自动检查(丢弃对原来文件所有的修改) |
24.使用缩写
为经常使用的单词或表达式创建缩写,可以用:ab命令,语法是:
:ab [short long]
删除一个缩写,可以有命令:una,语法是:
:una short
例 ,为暑假的实习工作准备一张履历表,需要不停地输入字符串“exceptionally gifted",重复输入会让人感到很厌烦,此时可创建一个缩写,减少大量的文字输入工作。
:ab eg exceptionally gifted
有时觉得此缩写无用了,可以删除它了。
:una eg