vi/vim 基本使用方法
(网上收集,转载过多,不知道原作者)
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令。由于对Unix及Linux系统的任何版本,vi编辑器是完全相同的,因此您可以在其他任何介绍vi的地方进一步了解它。Vi也是Linux中最基本的文本编辑器,学会它后,您将在Linux的世界里畅行无阻。
1、vi的基本概念
基本上vi可以分为三种状态,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
1) 命令行模式command mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode。
2) 插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。
3) 底行模式(last line mode)
将文件保存或退出vi,也可以设置编辑环境,如寻找字符串、列出行号……等。
不过一般我们在使用时把vi简化成两个模式,就是将底行模式(last line mode)也算入命令行模式command mode)。
2、vi的基本操作
a) 进入vi
在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面:
$ vi myfile
不过有一点要特别注意,就是您进入vi之后,是处于「命令行模式(command mode)」,您要切换到「插入模式(Insert mode)」才能够输入文字。初次使用vi的人都会想先用上下左右键移动光标,结果电脑一直哔哔叫,把自己气个半死,所以进入vi后,先不要乱动,转换到「插入模式(Insert mode)」再说吧!
b) 切换至插入模式(Insert mode)编辑文件
在「命令行模式(command mode)」下按一下字母「i」就可以进入「插入模式(Insert mode)」,这时候你就可以开始输入文字了。
c) Insert 的切换
您目前处于「插入模式(Insert mode)」,您就只能一直输入文字,如果您发现输错了字!想用光标键往回移动,将该字删除,就要先按一下「ESC」键转到「命令行模式(command mode)」再删除文字。
d) 退出vi及保存文件
在「命令行模式(command mode)」下,按一下「:」冒号键进入「Last line mode」,例如:
: w filename (输入 「w filename」将文章以指定的文件名filename保存)
: wq (输入「wq」,存盘并退出vi)
: q! (输入q!, 不存盘强制退出vi)
3、命令行模式(command mode)功能键
1). 插入模式
按「i」切换进入插入模式「insert mode」,按“i”进入插入模式后是从光标当前位置开始输入文件;
按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;
按「o」进入插入模式后,是插入新的一行,从行首开始输入文字。
2). 从插入模式切换为命令行模式
按「ESC」键。
3). 移动光标
vi可以直接用键盘上的光标来上下左右移动,但正规的vi是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格。
按「ctrl」+「b」:屏幕往“后”移动一页。
按「ctrl」+「f」:屏幕往“前”移动一页。
按「ctrl」+「u」:屏幕往“后”移动半页。
按「ctrl」+「d」:屏幕往“前”移动半页。
按数字「0」:移到文章的开头。
按「G」:移动到文章的最后。
按「$」:移动到光标所在行的“行尾”。
按「^」:移动到光标所在行的“行首”
按「w」:光标跳到下个字的开头
按「e」:光标跳到下个字的字尾
按「b」:光标回到上个字的开头
按「#l」:光标移到该行的第#个位置,如:5l,56l。
4). 删除文字
「x」:每按一次,删除光标所在位置的“后面”一个字符。
「#x」:例如,「6x」表示删除光标所在位置的“后面”6个字符。
「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符。
「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符。
「dd」:删除光标所在行。
「#dd」:从光标所在行开始删除#行
5). 复制
「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
「#yw」:复制#个字到缓冲区
「yy」:复制光标所在行到缓冲区。
「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能。
6). 替换
「r」:替换光标所在处的字符。
「R」:替换光标所到之处的字符,直到按下「ESC」键为止。
7). 回复上一次操作
「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复。
8). 更改
「cw」:更改光标所在处的字到字尾处
「c#w」:例如,「c3w」表示更改3个字
9). 跳至指定的行
「ctrl」+「g」列出光标所在行的行号。
「#G」:例如,「15G」,表示移动光标至文章的第15行行首。
4、Last line mode下命令简介
在使用「last line mode」之前,请记住先按「ESC」键确定您已经处于「command mode」下后,再按「:」冒号即可进入「last line mode」。
A) 列出行号
「set nu」:输入「set nu」后,会在文件中的每一行前面列出行号。
B) 跳到文件中的某一行
「#」:「#」号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字15,再回车,就会跳到文章的第15行。
C) 查找字符
「/关键字」:先按「/」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按「n」会往后寻找到您要的关键字为止。
「?关键字」:先按「?」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按「n」会往前寻找到您要的关键字为止。
D) 保存文件
「w」:在冒号输入字母「w」就可以将文件保存起来。
E) 离开vi
「q」:按「q」就是退出,如果无法离开vi,可以在「q」后跟一个「!」强制离开vi。
「qw」:一般建议离开时,搭配「w」一起使用,这样在退出的时候还可以保存文件。
5、vi命令列表
1、下表列出命令模式下的一些键的功能:
h
左移光标一个字符
l
右移光标一个字符
k
光标上移一行
j
光标下移一行
^
光标移动至行首
0
数字“0”,光标移至文章的开头
G
光标移至文章的最后
$
光标移动至行尾
Ctrl+f
向前翻屏
Ctrl+b
向后翻屏
Ctrl+d
向前翻半屏
Ctrl+u
向后翻半屏
i
在光标位置前插入字符
a
在光标所在位置的后一个字符开始增加
o
插入新的一行,从行首开始输入
ESC
从输入状态退至命令状态
x
删除光标后面的字符
#x
删除光标后的#个字符
X
(大写X),删除光标前面的字符
#X
删除光标前面的#个字符
dd
删除光标所在的行
#dd
删除从光标所在行数的#行
yw
复制光标所在位置的一个字
#yw
复制光标所在位置的#个字
yy
复制光标所在位置的一行
#yy
复制从光标所在行数的#行
p
粘贴
u
取消操作
cw
更改光标所在位置的一个字
#cw
更改光标所在位置的#个字
2、下表列出行命令模式下的一些指令
w filename
储存正在编辑的文件为filename
wq filename
储存正在编辑的文件为filename,并退出vi
q!
放弃所有修改,退出vi
set nu
显示行号
/或?
查找,在/后输入要查找的内容
n
与/或?一起使用,如果查找的内容不是想要找的关键字,按n或向后(与/联用)或向前(与?联用)继续查找,直到找到为止。
对于第一次用vi,有几点注意要提醒一下:
1、用vi打开文件后,是处于「命令行模式(command mode)」,您要切换到「插入模式(Insert mode)」才能够输入文字。切换方法:在「命令行模式(command mode)」下按一下字母「i」就可以进入「插入模式(Insert mode)」,这时候你就可以开始输入文字了。
2、编辑好后,需从插入模式切换为命令行模式才能对文件进行保存,切换方法:按「ESC」键。
3、保存并退出文件:在命令模式下输入:wq即可!(别忘了wq前面的:)
1、(motion)
fx 向后 移动到搜索字母上,x 可以是任意一个字母
tx 向后 移到搜索字母的左边 (这真的很有用)
Fx 向前 移到搜索字母上
Tx 向前 移到搜索字母的左边
; 重复上面四种命令 ,也是重复命令 不过方向取反
. 重复上一个操作
以上命令都是在本行移动
,. 当前行 ,%当前文件
gd to definition of the current word
w:上一个词。 b:下一个词。(以nonword的特殊字符作为word的边界,如.,-等
W 上一个词 B 下一个词 (以空格作为word的边界)又称长单词
e: 下个词的最后一个字母 ge 上个词的最后一个字母
0:移动光标到当前行首。
gm 移动到行正中
$:移动光标到行尾。
2$ 下一行行尾
^:移动光标到当前行的第一个字母位置。
) ( 移动光标到上/下一个句子。
{ } pre/next paragraph
[{ ]} begin/end of block
[[ ][ 代码块的开头和结尾 假设{和}位于第一列的情况下成立
[( ]) 括号范围内前后移动
gD 跳转到局部变量的定义处
+ - 下一行的开始 上一行的开始(非空)
% matching parenthesis
5、在整个文件里面有效移动光标
gg:到文件首 G:到文件尾
numG:移动光标到指定的行(num)。(比如 10G 就是到第 10 行)
H:移动光标到屏幕上面 M:移动光标到屏幕中间 L:移动光标到屏幕下面 当前屏幕的操作
nH 光标到当前屏幕的第n行
nL 光标到当前屏幕的倒数第n行
zt scroll to top
zz scroll to middle 有用 把当前编辑行置于屏幕中间
zb scroll to bottom
ctr+B/b ctr+F/f pre/next page
ctr+U/u ctr+D/d pre/next half page
ctr+e ctr+y 上/下滚一行
*:读取光标处的单词,并且移动光标到它再次出现的地方。
#:读取光标处的单词,并且移动光标到它上次出现的地方。
g* 它不完全匹配光标所在处的单词,而是匹配包含该单词的所有字符串
g# 它不完全匹配光标所在处的单词,而是匹配包含该单词的所有字符串
/text:从当前光标处开始搜索字符串 text,并且到达 text 出现的地方。必须使用回车来开始这个搜索命令。如果想重复上次的搜索的话,按 n
?text:和上面类似,但是是反方向。
/\<text\> 搜索完整的text单词
/ab\{3,5} 对b匹配3-5次
\{0,1}匹配0或1次 跟\=一样
\{0,} 匹配0次或多次 跟\*一样
\{1,} 匹配1次或多次 跟\+一样
\{3} 匹配3次
/ab\{-1,3} 将会匹配abbb中的ab 意思是尽可能的避免重复
/a.\{-}b 其中{-}匹配前面的项一次或0次 尽可能地少 一般这个模式本身只可能匹配到0次
因此 这个命令 只会匹配到axbxb中的axb
/a.*b 则会尽可能多的匹配 因而对于axbxb 会匹配整个的axbxb
/the\nword 匹配以the结束而且下一行以word开始的行
\_s 匹配空格或断行
/the\_sword the 与word 之间有空格或断行
/\d\u{3}\d\{3} 匹配一个数字 三个大写字母 单个数字
/joe/s-2 所查找之处往前两个字符
搜索完按n重复上次查找 N逆向上次查找
3n 向下搜索第三个
ma `a mark/jump to a 'a 转到标记所在的行头(行头)
`.:到你上次编辑文件的修改点。这个命令很有用,而且你不用自己去标记它
'. 到上次修改的行
`` 在上次编辑的地方与本次的地方来回跳转(仅限使用命令的跳转)
`0 上次编辑的地方
ctr+O ctr+I 往前或往后跳 编辑的地方
:s/old/new 将当前行中old替换为new 只替换一次
:s/old/new/n search and replace n times
:s/old/new/g 将当前行中的old替换为new,全部替换
:.,$ s/old/new/g 将当前行至文件末尾中的old替换为new,全部替换
:.,$ s/old/new 将当前行中至文件末尾中的old替换为new,每行至替换一次
:1,$ s/old/new 或 :% s/old/new 将文件所有行中的old替换为new,每行只替换一次
:1,$ s/old/new/g 或 :% s/old/new/g 将文件中的所有行的old替换为new,全部替换
%是目前编辑的文章 #是前一次编辑的文章
:?^chapter?-1,/^chapter/+2 s=grey=gray=g 将上个chapter与下一个chapter之间的所有的grey替换为gray,用=替换/ 来避免过多的/
:g/foobar/s/bar/baz/g 搜索foobar 然后替换为foorbaz 不会影响到jailbars
:g/\(foo\)\(bar\)/s/\2/\1baz/g
特殊的序列 & 所有查找时匹配到的东西
\[1-9] 1到9号用\(\)括起来的东西
\u 下一个字符被变成大写
\U 以后 所有的字符都 变成大写 知道遇到\e
\l 下一个字符变成小写
\L 以后的字符都变成小写
:.,.+4 从当前行到下面第四行
:`t,`b 从上一个标记t到下一个标记b
~ 改变当前字母的大小写类型
ggguG : 将当前编辑文件内容全部转换成小写
g~m 切换大小写 动作m跨越的行
guw 变小写
gUw 变大写
xp 当前字母和后一个字母的位置进行替换
ddp 两行互换位置2.高效的输入
1、使用关键词自动完成
输入一个长词的一部分,按住 Ctrl,再按 N或n)如果 VIM 会一直循环它找到的匹配的字符串。
2、聪明的进入插入模式
i:在当前字符的左边插入 I:在当前行首(第一个非空字符)插入
gI 在第一列插入文本
a:在当前字符的右边插入 A:在当前行尾插入
o:在当前行下面插入一个新行 O:在当前行上面插入一个新行
R ENTER REPLACE MODE 替换
S 替换掉光标所在行 再进入编辑模式
:> 本行缩进
:< 取消本行缩进
<< >> 左移或右移当前段落一个移动宽度(shiftwidth)
:>n 缩进连本行在内的n行
:<n 取消连本行在内的n行的缩进
c{motion}:删除 motion 命令跨过的字符,并且进入插入模式。比如:c$,这将会删除从光标位置到行尾的字符并且进入插入模式。ct!,这会删除从光标位置到下一个叹号(但不包括),然后进入插入模式。被删除的字符被存在了剪贴板里面,并且可以再粘贴出来。
d{motion}:和上面差不多,但是不进入插入模式。
3、有效的移动大段的文本
模式:
v:按字符选择。经常使用的模式,所以亲自尝试一下它。
V:按行选择。这在RGB(0x20,0x6a,0x4f)多行的文本的时候特别有用。
CTR+v:按块选择。采用xbeta的_Vimrc文件时
ctr+q 按块选择。
4、在可视选择模式下剪切和拷贝
一旦你高亮了选区,你或许想进行一些操作:
d:剪贴选择的内容到剪贴板。
y:拷贝选择的内容到剪贴板。
c:剪贴选择的内容到剪贴板并且进入插入模式。
在非可视选择模式下剪切和拷贝
如果你很清楚的知道你想拷贝或者剪切什么,那你根本就不需要进入可视选择模式。这样也会节省时间:
d{motion}:剪切 motion 命令跨过的字符到剪贴板。比如,dw 会剪切一个词而 dfS 会将从当前光标到下一个 S 之间的字符剪切至剪贴板。
y{motion}:和上面类似,不过是拷贝。
y2fa 表示拷贝从当前光标到光标后面的第二个a 字符之间的内容。
:12,y 表示拷贝第12 行到光标所在行之间的内容。
:,24y 表示拷贝光标所在行到第24 行之间的内容。
c{motion}:和 d{motion} 类似,不过最后进入插入模式。 cw 改变一个词
cc change line d$ 删除从现在光标所在位置 (包括)至行尾
cw change word cw 与 dw 由区别 前者不去最后的一个空格 后者去
rc 将光标下的字符替换为c
R replace beginning at cursor
dd:剪切当前行。 yw 复制的内容包括word之后的空白字符
ndd delete n lines
ndw delete n words
dw delete a word
yy拷贝当前行。
Y 拷贝当前行。
Vyp 复制一行
cc 剪切当前行并且进入插入模式。
D 代表 d$ 删除到行尾的内容
C 代表 d$ 修改到到行尾的内容。
x 代表dl 删除当前光标下的字符
X 代表dh 删除当前光标左边的字符
daw 删除一个单词 (包括其后的空格
cis 删除一个句子
cas 删除一个句子 (包括后面的空白
diw 删除光标上的单词
daw 删除光标上的单词 (包括空白字符
用d或x删除时 同时被删除的内容被保存起来
s 代表cl 修改当前光标下的字符
S 代表cc 修改当行
J jion two lines
r 替换之后 不进入插入模式
gum gUm 小写/大写 动作m跨越的文本
<m >m 左移/右移 动作m跨越的行
n<< n>> 将n行左移或右移一个缩进位
5、粘贴
p 粘贴到光标后
大写P 粘贴到光标前
6、使用多重剪贴板
很多编辑器都只提供了一个剪贴板。VIM 有很多。剪贴板在 VIM 里面被称为寄存器(Registers)。你可以列出当前定义的所有寄存器名和它们的内容,命令为“:reg”。最好使用小写字母来作为寄存器的名称,因为大写的有些被 VIM 占用了。
使用寄存器的命令为双引号 “。
比如:我们要拷贝当前行到寄存器 k。你应该按 “kyy。(你也可以使用 V”ky。为什么这样也可以呢?)现在当前行应该已经存在了寄存器 k 里面直到你又拷贝了一些东西进入寄存器 k。现在你可以使用命令 “kp 来粘贴寄存器 k 里面的内容到你想要的位置。
7、避免重复
. (小数点符号), 需要在normal下去执行 将会重复上一个修改命令。
u 撤销上次操作
U 撤销一行的操作 不管几次
ctr+R 恢复撤销
CTR+Y 重做
8、使用数字
3j 将会把光标向下移动三行。
10dd 将会删除十行。
y3″ 将会拷贝从当前光标到第三个出现的引号之间的内容到剪贴板。
:w save(:wq save and quit) ZZ保存后退出
:q quit(:q! quit anyway)
:only 关闭除当前窗口外的其它窗口
:qall 关闭所有的窗口 如果有为保存的文件 则自动跳到为保存的文件
:wall 全部保存
:e x edit file x
:e x 放弃修改重新载入当前的文件x
:n new window
:h vim help
:xx jump to line #xx
ctr+N CTR+P auto-complete next/prev keyword 插入模式下的单词自动完成
ctr+x+l 自动补全整行内容
ctr+x+f auto-complete file name 搜索可匹配的文件名并完成
缩写:
:abbr sprt system.out.println
在编辑状态下输入sprt后再输入其他非字母符号会自动扩展
ctr+W 在多个窗口间切换
:set nu 或 :set number 显示行号
:set nonu 或 :set nonumber 消除行号
:set ruler 设置vim在右下角显示光标的位置
:set incsearch 自动匹配
:set hlsearch 搜索时自动匹配
:set nohlsearch
:set ignorecase 忽略大小写
:set wrapscan 设置循环搜索
:set textwidth=30 设置自动换行 并将 最大长度设为30
:set background=dark
:set background=light
:set patchmode=.org 编辑data.txt 时 保存原始文件为data.txt.org
:reg 查看剪切板中的内容
gf 打开光标处的文件名
pwd 获取当前工作目录
多窗口:
:vsp :sp vertically/horizontally split 纵向或横向分屏
:ctrl+w-w 切换窗口
:close 关闭窗口 可以阻止关闭最后一个VIM窗口
:only 关闭除了当前窗口之外的所有的窗口
ctrl+w++ 增加当前窗口的高度
:diffs split and diff 分屏比较
ctr+W p to last accessed window 移动到上个屏幕
ctr+W w to next window
:12 go to 12th line
:r file append file into vim/vi
:f file change current filename to file
:w save changes and stay in file
:q quit and ignore changes
:q! force quit and ignore changes `
:wq quit and save
:nw file write file to the nth lines
:e filename edit new file
:r filename insert the new file to the position of the current cursor
:0r filename 将文件filename的内容插入到文件的开头
:.,$w filename 将当前正在编辑的文件中的当前行至最后一行写到新的文件filename中
:.,$w >>filename 将当前正在编辑的文件中的当前行至最后一行写到追加到已有的文件filename中
z redraw the screen
zz put the cursor to middle
zt 光标到所在行到屏幕顶端
zb 光标所在行到屏幕下端
qm 录制宏到寄存器m
@m 执行寄存器中的宏
一些设置
:set go=
隐藏菜单
:set shiftwidth=4 一次移动4个单位 用于<和>命令 移动的宽度
5>> 光标后5行向右移动一个tab
:12,24> 将12至24行的数据都向右移动一个tab
:12,24>> 将12至24行的数据都向右移动两个tab
<% or >% 来将({[等括号之间的文本都左移一个tab单位
shiftwidth(缩进的空格数,设置自动缩进时 会自动缩进4空格
tabstop(制表符的宽度)tab的宽度
expandtab(是否在缩进和遇到Tab键时使用空格替代;使用noexpandtab取消设置);
softtabstop(软制表符宽度,设置为非零数值后使用Tab键和Backspace时光标移动的格数等于该数值,
但实际插入的字符仍受tabstop和expandtab控制);
autoindent(自动缩进,即每行的缩进值与上一行相等;使用noautoindent取消设置);
shiftwidth=4 tabstop=4:很多Windows出身的程序员会习惯这样的设置,让缩进等于制表符宽度。
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
模式行有好几种形式。本文只介绍上面的这种形式(其它形式类似,请自行参考“:help
modeline”):行首的“/*”和尾部的“*/”告诉C 编译器这是一行注释,不是代码的一部分;而
Vim可通过后面的“vim:”识别出模式行的开始(必须出现在行首或前面有一个空白字符);后面则是
“set”和空格间隔开的一串Vim选项;“:”表示模式行结束。
:set softtabstop=4 使得在第一列按下一个制表符 光标就会向前移动4个空格 再次按下时
会增加一个制表符 总共8列
:set expandtab 只使用空格 制表符会被相应宽度的空格代替
:colo evening 背景变黑
语法高亮:
:syntax keyword xType int long char 将int long char定义为组xType
:highlight link xType Type 将xType与Type联系起来 使得他们有相同的语法高亮
定义自己的映射键
在normal下: 用:map <F2> ggVG
在insert下: 用:imap <F2> ggVG
组合命令:
:%s/ /^M/g 将所有的空格替换为换行
ggVG 全选
:%s/$/!/g 所有行末尾加!
:%s/old/\r&/gc 表示将old替换为前面加换行在加old
:s/fred/<c-r>a/g : 将fred 替换为寄存器a 里的内容,<c-r>为按下Ctrl与r,
然后输入a 后,寄存器a 的内容会出现在命令行
:s/fred/<c-r>asome_text<c-r>s/g
:s/fred/\=@a/g : 与第一条的作用相同,但是更优雅一些,
因为不会在命令行显示寄存器的内容
:%/为../&\r 将”为**“ 替换为 ”为**“加回车
编辑命令时:<left>代表向左一个字符
<right>代表向左一个字符
<shift+left>代表向左一个单词
<shift+right>代表向右一个单词
home 至命令行首
end 至命令行尾
ctrl+w 删除光标前的整个单词
ctrl+u 删除光标之前的所有内容
tab键自动补齐所输入的较长的单词或者文件路径
1. 去掉所有的行尾空格:“:%s/\s\+$//”。
“%”表示在整个文件范围内进行替换,
“\s”表示空白字符(空格和制表符),
“\+”对前面的字符匹配一次或多次(越多越好),
“$”匹配行尾(使用“\$”表示单纯的“$”字符);
被替换的内容为空;由于一行最多只需替换一次,不需要特殊标志。这个还是比较简单的。
2.去掉所有的空白行:“:%s/\(\s*\n\)\+/\r/”。
这回多了“\(”、“\)”、“\n”、“\r”和“*”。
“*”代表对前面的字符(此处为“\s”)匹配零次或多次(越多越好;使用“\*”表示单纯的“*”字符),
“\n”代表换行符,“\r”代表回车符,“\(”和“\)”对表达式进行分组,使其被视作一个不可分割的整体。因此,这个表达式的完整意义是,把连续的换行符
(包含换行符前面可能有的连续空白字符)替换成为一个单个的换行符。唯一很特殊的地方是,
在模式中使用的是“\n”,而被替换的内容中却不能使用“\n”,而只能使用“\r”。原因是
历史造成的,详情如果有兴趣的话可以查看“:help NL-used-for-Nul”。
3. 去掉所有的“//”注释:“:%s!\s*//.*!!”。首先可以注意到,这儿分隔符改用了“!”,原
因是在模式或字符串部分使用了“/”字符,不换用其他分隔符的话就得在每次使用“/”字符
本身时写成“\/”,上面的命令得写成“:%s/\s*\/\/.*//”,可读性较低。命令本身倒是相
当简单,用过正则表达式的人估计都知道“.”匹配表示除换行符之外的任何字符吧。
4.去掉所有的“/* */”注释:“:%s!\s*/\*\_.\{-}\*/\s*! !g”。这个略有点复杂了,用到
了几个不太常用的Vim正则表达式特性。“\_.”匹配包含换行在内的所有字符;“\{-}”表示
前一个字符可出现零次或多次,但在整个正则表达式可以匹配成功的前提下,匹配的字符数越
少越好;标志“g”表示一行里可以匹配和替换多次。替换的结果是个空格的目的是保证像
“int/* space not necessary around comments */main()”这样的表达式在替换之后
仍然是合法的。
5、:g/./,/^$/join
:g/./ 一个全局命令, 查找那些至少有一个字符的行.
,/^$/ 指定一个范围, 从当前行开始(非空行)直到一个空行.
join ":join"命令把指定范围内的行连为一行.
6.对多个文件进行改动 例如把所有的c文件中的x_cnt变量替换为x_counter变量
先将所要修改的文件放到参数列表上 :args *.c
再执行命令 :argdo %s/\<x_cnt\>/x_counter/ge |update
解释::argdo 命令已另一个命令为参数
g是对每行中的所有的x_cnt进行替换
e是避免某些 文件中没有一个x_cnt可供替换 那就不进行下面的替换的情况
| 用来分隔两个命令 后面的update 命令会在文件有所改变时保存 没改变的则不进行操作
类似于argdo 命令:windo 会对所有的窗口都执行同样的操作
:buffer 则是对所有的缓冲区进行操作
:ls 可以查看缓冲区情况
:args 显示目前打开的文件
% 当前编辑文件
# 上次编辑文件
:previous 编辑上一个文件
:next 编辑下一个文件
:wprevious 保存并编辑上一个文件
:last 编辑最后一个文件
:first 编辑第一个文件
:lcd%:p:h 更改到当前文件所在的目录
lcd是仅仅改变当前窗口的工作路径 %表示当前文件的文件名
加上:p扩展为全名(带路径) 加上 :h 析出路径
8. :g/^\s*$/d 删除所有空行
恢复机制:
正在编辑一个文件help.txt时死机 则下次启用vim时用 :vim -r help.txt 来恢复
然后先存储在另一个文件:write help.txt.recovered 再比较这两个文件
如果正在编辑的文件没有名字 则用 :vim -r "" 来恢复所有可能的文件
:echo 3+8*9 会计算出值
一些组合命令:
:g/^/m 0 依此将每行移动到第0行的下一行 实现倒序功能
:g/^/+1 d 删除偶数行
:s/\n\n\@!// \n\n\@!是查找后面不跟回车的回车 然后替换为空格
:g/./,/^$/j /./标记非空行 /^$/查找后面的行直到出现空行 然后对二者进行合并
:v/ccc\|ddd/s/aaa/bbb/g 将aaa替换成bbb 条件是行中有ccc但不能有ddd
:g/ccc/if getline('.')!~'ddd'|s/aaa/bbb/g 首先标记匹配的ccc行 然后执行if命令 getline函数
则取得当前行 然后判断是否匹配ddd
如果不匹配(!~的求值为true)则执行替换
:g/^/,+2 d|,+6 m -1 每十行删除前后三行
:g/^/,+6 m -1|+1,+3 d 每十行删除前后三行
:g/if/+1,/elsif\|else/-1 t $ 将if与elsif或else之间的内容 复制到末尾
:g/^/put_ : 双倍行宽 (pu = put)
:g/^/m0 : 颠倒文件 (m = move)
:'a,'bg/^/m'b : 颠倒选中的 a 到 b
:g/^/t. : 重复行
:g/fred/t$ : 拷贝行从fred 到结尾
:g/stage/t'a : 拷贝行从stage 到 marker a(a 为标记的位置)
隔行替换
:g/^/ if line('.')%2|s/^/zz /
查找标记a 与b 间所有包含"somestr"的行,并全部复制到第一个包含"otherstr"的行后
:'a,'bg/somestr/co/otherstr/ 其中 co(py) or mo(ve)
用文件中的内容替换字符串,-d 表示删除上面的一行
:g/^MARK$/r tmp.ex | -d
:g/<pattern>/z#.5 : 带有上下文一并显示
:g/<pattern>/z#.5|echo "==========" : 优雅地显示
将g//和普通模式下的命令结合起来
:g/|/norm 2f|r* : 将第二个|替换为*号
全局命令和替换命令联姻 (强大的编辑能力)
:'a,'bg/fred/s/joe/susan/gic : 可以使用反向引用来匹配
:g/fred/,/joe/s/fred/joe/gic : 非行模式
:/fred/;/joe/-2,/sid/+3s/sally/alley/gIC 先找fred,然后找joe
:g/^/exe ".w ".line(".").".txt"
为每一行生成一个文件,文件名从1.txt 开始,依次为1.txt,2.txt,3,txt
xy\{2,}表示x后接至少两个y 相当于xyy\+或xyyy*
"ayy 将当前行复制到a缓冲区 "的作用是注释,以免当成插入
"ap 粘贴刚才复制的行
缓冲区在wim中的术语是registers 具体可以看:h registers
d,c,s,x,y等指令改变或删除的内容都是放在registers中的
:reg 命令可以查看缓冲区的内容 然后可以根据前面的标记加p复制需要的内容
冒号命令支持tab键补全功能
. 重复上一次的编辑动作(移动游标和冒号命令除外)、
:marks 可以得到所有的标签列表
vim+ 档案名 可以打开档案 并且游标会落在最后一行的行尾
vim+n 档案名 游标会落在第n行的行首
vim+/string 档案名 进入档案后游标会进入第一个要找到的string上 按n可以继续寻找
多当编辑有两种形式:
argument list 进入vim前所用的参数就是多档
buffer list 进入vim后另外再开其它的档
:n 编辑下一个档案
:2n 编辑下二个档案
:N 编辑前一个档案 适用于argument list
:sp(:vsp) filename 分割出一个窗口并打开文件filename
:rew 回到首文件
:e 档案名 在不离开vim的情形下再开其它档案 只要要编辑的档案在目前的目录下即可
:e# 或CTR+^ 编辑前一个档案 用于两档互相编辑时相当好用 #表示前一次编辑的档案
:ls 会列出目前buffer中的所有档案
编号后边有#的代表是前一个文件,可以通过:e#来进入,
%a 的代表是当前文件,
什么也没有的可以通过:bn 来进入,这里的n 代表文件编号。
:b 文件名或编号移至该文件。
:args 查看当前打开的所有的文件
:h pattern 可以查看regexp内容
:changes 列出改变列表 :h changelist 查看‘改变表转跳帮助’
:ju(mps) 列出跳转轨迹
:history 列出历史记录
:his c 命令行历史
:his s 搜索历史
"ayy@a : 把当前行作为命令执行
yy@" : 上面的匿名寄存器
u@. : 只执行键入的命令
使用外部sort 排序
:%!sort -u : 用sort 排序整个文件(结果覆盖整个文件)
:'a,'b!sort -u : 从mark a 到mark b 之间的内容进行排序
!1} sort -u : 排序一个段落
:g/^$/;,/^$/-1!sort : 将每个块排序(注意这个关键的;)
:badd file.c : 添加file.c 到buffer 列表
:b 3 : 前往第三个 buffer
:b main : 前往含有main的buffer 中 比如说 main.c
:sav php.html : 把当前文件存为php.html并打开
:sav! %<.bak : 换一个后缀名保存 (旧方法)
:sav! %:r.cfm : 同上
:sav %:s/fred/joe/ : 替换文件名
:sav %:s/fred/joe/:r.bak2 : 替换文件和后缀
:!mv % %:r.bak : 重命名当前文件
:e! : 打开未修改之前的文件
:w c:/aaa/% : 存储文件到指定位置
:e # : 编辑标记为#的文件在buffer 中
:rew : 返回到第一个可编辑的文件
:brew : 回到第一个buffer
:sp fred.txt : 分割窗口打开fred.txt
:sball,:sb : 把所有的 buffers 分割显示在一个窗口中 (超有用)
:scrollbind : 让每个分离的窗口,同步滚动
:map <F5> :ls<CR>:e # : 按F5 显示所有buffer, 并显示行号
:set hidden : 允许不保存当前buffer 而进行切换
V : 进入可视化行选择模式
gv : 重新选择
:s/.\{,69\};\s*\|.\{,69\}\s\+/&\r/g 在70 列的时候换行
vim -c "%s/ABC/DEF/ge | update" file1.c 在打开一个文件时执行多条命令
vim -c "argdo %s/ABC/DEF/ge | update" *.c 在一组文件上执行多条命令
vim -c "argdo /begin/+1,/end/-1g/^/d | update" *.c 从一系列文件中删除一块区域
在文件中插入行号
:g/^/exec "s/^/".strpart(line(".")." ", 0, 4)
:%s/^/\=strpart(line(".")." ", 0, 5)
:%s/^/\=line('.'). ' '
命令使用于多个文件
:argdo %s/foo/bar/e : 在所有文件上操做 :args
:bufdo %s/foo/bar/e
:windo %s/foo/bar/e
:argdo exe '%!sort'|w! : 包含外部命令
REGEXP:
* 0次以及多次
+ 一次以及以上
= 0或1次
| or的意思
:%s/\([a-z]\)\1/test/g 将aa,bb,cc,……zz替换为test
:%s/[a-z][a-z]/test/g 不是一个意思 会将aa,ab,ac,等都替换为test
mastering regular expressions(o'reilly&asscociate) 书里详细介绍了正则表达式
\{m,n\} 前面部分的从m次至n次出现
\{m\} 精确m次出现
\{m,\} 大于等于m次出现
/\(foo\|bar\)\+ 匹配 foo foobar foofoo barfoobar
/.*fred\&.*joe 搜索同时包括fred 跟joe的行
/\<\d\d\d\d\> 搜索独立的4位数字
/\D\d\d\d\d\D 搜索恰好4位的数字
/<\zs[^>]*\ze> 匹配<与>所包含的内容 但不包含<>
/<\@<=[^>]*>\@= 查找<与>所包含的内容
/<\@<=\_[^>]*>\@= 多行匹配<与>所包含的内容
/<!--\_p\{-}--> 匹配<与>所包含的所有内容 {-}是非贪婪匹配
:%s/^\n\+/\r/ 压缩空行,多个替换为一个
/<\zs[^>]*\ze> 匹配<>之间的内容
/<\@<=[^>]*>\@= search for tag contents, ignoring chevrons 匹配<>标签中的内容,而忽略<和>本身
/<\@<=\_[^>]*>\@= search for tags across possible multiple lines
:%s/\r//g delete dos returns ?M
:%s/\r/\r/g turn dos returns ?M into real returns (fixes joined lines)
在一个模式中的“或”操作符是\| 例如 /foo\|bar 他匹配到foo 或着是bar
/\(foo\|bar\)\+ 它匹配到foo foofoo foobvar barfoobar
/end\(if\|while\|for\) 匹配的是endif endwhile endfor
/forever\&... 只会匹配到forever中的for 而不会匹配到fortuin的for
/[a-z]可以匹配a到z中的一个字母
/[0123456789abc] 可以匹配0123456789abc中的任意一个字母
/[0-9a-c] 与上面等价
/[^a] 匹配除a之外的任意字符
/"[^"]*" 其中[^"]表示除双引号之外的任意一个字符 总的命令将会匹配到“foo”或“3!x”
\d 数字 等价于[0-9]
\D 非数字 等价于[^0-9]
\s 空白字符 等价于[ ]包含<tab><space>
\S 非空白字符 等价于[^ ]
\l 小写字母 等价于[a-z]
\L 非小写字母 等价于[^a-z]
\u 大写字母 等价于[A-Z]
\U 非大写字母 等价于[^A-Z]
\i 匹配标识符字符[a-zA-Z0-9]
\I 匹配[a-zA-Z]
\w 匹配一个字母、数字、或下划线[a-zA-Z0-9_]
\_s* 任何空白字符包括换行
\_.* 任何字符包括换行
高级正则表达式
1./\s*\<\(return\|else\)\@!\w\+\s\+\w\+\s*([^)]*)\s*;\@!\s*$ 查找多由c语言中的函数
\< 零长度匹配,表示单词的开始
\@! 零长度匹配 表示要求他前面的内容不存在
2.要求是将
<par type="I" flags="RO">
</par>
<par type="I" flags="RO,H">
</par>
变成
<par type="I" flags="RO" id="0">
</par>
<par type="I" flags="RO,H" id="1">
</par>
方法一:
第一步,增加id="":
:g/^<par type/s/>$/ id="">/g
第二步,增加数字:
:let i=0 | g/^<par type/s/id="\zs\ze">$/\=i/| let i=i+1
这是用|号(逻辑或的符号,不是字母)连接的三个语句,
前后两个就是给i赋初值和递增,
id="\zs\ze">$ \zs 和\ze 是"零长度匹配",在这两个中间的才作为匹配内容,
这个语句就是只匹配双引号中间的内容,
这样不会把其他有用的地方替换掉了
\=i \=是把后面的字符串当成表达式来对待,在这里就是i 的值
方法二:
这是用一步解决的方法:
:let i=0 | g/^<par type/s/>$/\=substitute(" id = \"0\">", "0", i,"")/| let i = i+1
和上面的方法基本相同,就是替换右尖括号,不过这次是替换为substitute(" id = \"0\">", "0", i,"")
这是一个替换函数,就是在id=0中查找第一个0,并替换为i 的值,最后一个参数是{flag},一般为空.
08.08.19 我自己也写了一个,和上面的基本一样,就是不用substitute函数而已
:let i = 1 | g/^<par type=/s/>$/\=" id = " . i . ">"/ | let i += 1
其中\=表示后面是个表达式,小数点用以连接字符串的几个部分,中间用了i 的值
3. 每行前面加上行号
法一:
:g/^/exec "s/^/".strpart(line(".")." ", 0, 4)
法二:
:%s/^/\=strpart(line(".")." ", 0, 4)/g
line()返回一个行数,特别的,
line(".")返回当前光标所在行的行数,其他的参数见:h line()
g/^/exec是对所有行执行一个或多个命令,具体可以:h exec 来查看,
每个命令必须用字符串,也就是要放在双引号里面,多个命令间用空格分割.
在上面的例子中,后面只有一个命令,但是这个命令是用小数点连起来的一个字符串
4.如下的赋值
firstline=1 //comment line 1
secondline=2 /*comment block 1*/
thirdline = 3//comment line 2
forthline= 4/*comment block 2*/
fifthline =5
希望整理成
firstline = 1 //comment line 1
secondline = 2 /*comment block 1*/
thirdline = 3 //comment line 2
forthline = 4 /*comment block 2*/
fifthline = 5
下面是我写的语句,比较长,应该还有更好的写法,以后有改进再补充
:g/=/s#\v(.*)\=\s*(((//|/\*)@!.)*)\ze(//|/\*)?#\=strpart(submatch(1) . " ",0,13) . "= " .
strpart(submatch(2) . " ",0,10)# | s/\s*$//
前面紫色部分,查找所有包含等号的行,然后执行后面两个命令,
第一个命令是橘黄色的部分,第二个命令是蓝绿色部分,
第二个命令就是去掉行末的空格,这个不需要多解释,重点解释第一个命令
s#a#b#是一个替换的命令,这里用#做分隔符,是因为后面的表达式中有斜杆/,
如果用斜杆作为分隔符,则表达式中的斜杆需要转义,稍显累赘
\v表示后面的正则表达式中,除了字母和数字和下划线和斜杆,其他的都作为特殊字符对待,
有这个设置的好处,是后面可以省掉好几个用来转义的反斜杆,
像\(\)\+这些都可以简写成()+
\= 匹配一个等号
\s* 匹配0个或0个以上的空白符
加粗的部分是一个比较重要的地方,一共三层括号,最外层括号使这个括号内部的内容成为一个子匹配,
在后文中的submatch(2)就是指的这一部分,
后面的一个*号,表示第二个括号内的内容可以匹配0 次或0 次以上.
第二个括号内部,@!是个"零长度匹配",表示前面第三层括号内的内容不能出现,
小数点匹配除了换行符外的任意字符,
第三层括号里面,就是c语言注释的两种形式,//和/*,中间用|连接,表示"或"的关系.
整个粗体部分的意思就是,匹配尽量长的,且不是C语言注释的内容.
\ze 匹配结束,后面的所有内容只是作为限制条件,
在替换的时候,只会替换\ze之前的内容后面的括号和粗体部分的第三层括号内容是一样的,
后面的问号表示匹配0次或1次,因为不是所有的行都有注释的后面就是替换成的内容了,
strpart 函数相当于VB 中的mid 函数,就是取字符串从某个位置开始的一段内容,
这里用了一个小技巧(虽然写起来挺长的,但是想法简单),
就是比如要把一个字符串处理成13 个字符的长度,不足的位置补空格,
我们就先在这个字符串后面加上13个空格,然后截取整段内容的前13个字符,
这样就满足要求了,还有其他的方法,比如用
另外一个函数submatch()表示的是前面用查找的时候的子匹配,也就是在括号中的内容,
submatch(0)对应这个匹配的内容,submatch(1)对应(.*)的内容,
submatch(2)对应粗体部分的内容
剩下的需要注意的地方,就是这里的小数点相当于VB中的&,是作为字符串的连接符号.
然后在等号后面空两格,等号后面原有的空格无论多少都去掉,然后把后面的内容,
到注释符号前面都整理成10个字符(不足补空格),最后才是注释
这样第一个命令执行后,对于没有注释的行,会多出来10个空格,不太好看,
所有就加了第二条命令,去掉行末的空白
5.使用vim匹配两个特殊字符之间的内容并替换
举例如下:
fileA:
Mark
..............
Mark
......
Mark
..............
Mark
......
Mark
..............
Mark
如果要把Mark之间的内容替换成:ABCD.
那么应该使用正则表达式:g/Mark\_.\{-}Mark/ s//ABCD/g
如果要匹配第一个Mark到最后一个Mark,并替换成ABCD,
那么应该使用正则表达式:g/Mark\_.*Mark/ s//ABCD/g
6.
这里以编写C语言程序为例, 假设,我们最终想完成的代码如下:
#define BIT_MASK_1 (1 << 0)
#define BIT_MASK_2 (1 << 1)
#define BIT_MASK_3 (1 << 2)
#define BIT_MASK_4 (1 << 3)
#define BIT_MASK_5 (1 << 4)
#define BIT_MASK_6 (1 << 5)
#define BIT_MASK_7 (1 << 6)
#define BIT_MASK_8 (1 << 7)
#define BIT_MASK_9 (1 << 8)
#define BIT_MASK_10 (1 << 9)
#define BIT_MASK_11 (1 << 10)
#define BIT_MASK_12 (1 << 11)
#define BIT_MASK_13 (1 << 12)
只需要先写好第一行,如下:
#define BIT_MASK_1 (1 << 0)
然后,我们回到Normal模式,在这一行上输入“Y12p",拷贝此行,然后粘贴12次。这样,我们得到总
共13行上面的内容。
现在使用"V12j"命令选中这13行,然后使用两次替换命令:
:'<,'>s/BIT_MASK_\zs\d*\ze/\=line(".") - line("'<") + 1
:'<,'>s/\zs\d*\ze)$/\=line(".")-line("'<")
其中'<,'> 为我们所选中的区域 (:help '<,:help '> )
line(".") 当前光标所在行的行号 (:help line() )
line("'<") 我们所选区域中第一行的行号 (:help line() )
7.
UniqueID2 = lview.focusedItem.subItems.opIndex(0).text;
Parent = lview.focusedItem.subItems.opIndex(0).text;
Children = lview.focusedItem.subItems.opIndex(0).text;
login = lview.focusedItem.subItems.opIndex(1).text;
txtCust.text = lview.focusedItem.subItems.opIndex(2).text;
txtProj.text = lview.focusedItem.subItems.opIndex(3).text;
替换为
UniqueID2 = lview.focusedItem.subItems.opIndex(0).text;
Parent = lview.focusedItem.subItems.opIndex(1).text;
Children = lview.focusedItem.subItems.opIndex(2).text;
……
用
:let n=0 | g/opIndex(\zs\d\+/s//\=n/|let n+=1
其中: | 用来分隔不同的命令 (:help :bar )
8.
g/pattern1/;/pattern2/-1d pattern1与pattern2之间的内容删除,包括pattern1所在的行但是不包括pattern2所在的行
g/pattern1/;/pattern2/-1move $ 将pattern1(包括此行)至pattern2所在行之间的内容移动到文章末
:g/firstcatalog/ 显示所有的fistcatalog
:g/firstcatalog/nu 显示所有fistcatalog以及所在的行号
:g/firstcatalog/z#=4 显示所有firstcatalog以及附近的4行 可以用 :h :z 看到详细说明)
:g!/firstcatalog/ 显示不包含firstcatalog的行
/bugs\(\_.\)*bunny 匹配所有bugs到bunny的字符串
/fred\_s*joe/i 匹配fred 开始到joe,之间一定得是空白字符
/bugs\(\_.\)*bunny 匹配所有bugs到bunny的字符串
:%s/^\n\{3}// ;: 删除连续3个空行
:%s/^\n\+/\r/ ;: 压缩空行,多个替换为一个
:%s,\(all/.*\)\@<=/,_,g ;: 用 _ 替换 "all/"之后的 /
:'a,'bg/fred/s/dick/joe/igc 非常有用 'a,'b指定一个范围:marka ~ mark b
:g/fred/,/joe/d : 删除所有的从fred 到joe
:%s/[.!?]\_s\+\a/\U&\E/g 大写所有句子的第一个字母
宏替换:
:nmap <F2> :nohls<cr> 取消被搜索字串的高亮
:nmap <F9> <C-W>w 命令模式下转移光标到不同窗口
:imap <F9> <ESC><F9> 输入模式下运行<F9>
:nmap <F12> :%s= *$==<cr> 删除所有行尾多余的空格.
:imap <F12> <ESC><F12> 同上
/joe/e : 设置光标到匹配"joe"的末尾
/joe/e+1 : 设置光标到匹配"joe"的末尾再后移一位
/joe/s-2 : 设置光标到匹配"joe“的开头再前移两位
/joe/-2 : 设置光标到匹配"joe“的行再向上移两行的开头
在一行里写多种命令:
:%s/\f\+\.gif\>/\r&\r/g | v/\.gif$/d | %s/gif/jpg/ :
将所有带有.gif的行,前后均加入一个空行;
将不带有.gif 字样的行全部删除;
将所有行中的gif换成jpg;
注意三条语句,一旦某一条失败,则不执行下面的语句
三个在折叠的表达式比较常用几点:
v:lnum 内置变量,表示是“当前行的行号”。:help v:var 查看更多内置变量。
getline() 函数用以返回指定行的内容。
?: 三元条件语句。见:help expr1
v:lnum>=8&&v:lnum<=20?1:0
v:lnum>=8\ &&\ v:lnum<=20\ ?\ 1:0
:set foldexpr=(v:lnum>=8&&v:lnum<=20?1:0)
如果一行以@samp{#}开始,折叠。
:set foldexpr=getline(v:lnum)=~/^#/?1:0
以每5行为一组折叠
set v:lnum%5-1?1:'>1'
用正则表达式@samp{.}判断当前行是否含有文字。
set foldexpr=getline(v:lnum)=~'.'?1:0
在文章的末尾加入
vim: ro: fdm=expr: fde=getline(v\:lnum)=~'.'?1\:0:
foldtext=foldtext().v\:folddashes.getline(v\:folds
tart+1): foldcolumn=2
则每次打开文件会折叠(方式是空行之间的折叠在一起)
导出折叠的部分到笔记.txt
:folddoclosed .w! >>笔记.txt
如果folddoclosed 只对当前关闭的折叠有效,要导出所有的折叠先使用指令zR
删除所有的marker用 :g/{{{/norm zD
在'.vimrc'(windows中是'_vimrc')中加入,下面的内容:
" 根据邮件的后缀名进行相关的设置。如果打开的文件后缀名是
'.eml',则当成邮件处理。
autocmd! BufReadPre *.eml se fdm=expr
fde=v:lnum==1?1:getline(v:lnum)=~'^$'?0:'='
fdt=Mailfdt(v:foldstart,v:foldend) ft=mail | syn on
" 定义函数,用来返回折叠的标题。
" 以折叠的第一和最后一行的行号为参数
func! Mailfdt(fst,fen)
let fst=a:fst
" 保存邮件的标题和发信人
let hfrom=''
let hsub=''
let tline=''
while a:fen!=fst
let tline=getline(fst)
" 判断当前行是否是我们感兴趣的行
" 如果是则保存
if tline=~'^From: '
let hfrom=tline
elseif tline=~'^Subject: '
let hsub=tline
endif
let fst=fst+1
endwhile
" 返回相关信息
if strlen(hfrom) || strlen(hsub)
return hsub . "\t\t\t" . hfrom
else
return getline(a:fst)
endif
endfunc
在加入上面的内容后,我们现在用Vim打开邮件(实际是以.eml作后缀名的文件)
看看,是不是清爽多了!
这是比较不常用但又可能比较有用的内容。使用:help查看相关信息。
v:foldstart 内置变量只读变量记录只前所在折叠的起始行号
v:foldend 内置变量结束行号,其余同上
foldlevel() 函数返回指定行的折叠层级
'foldlevel' 设置项只有高于这个值的折叠层级才会进行折叠
'foldnestmax' 设置项指定最深的嵌套数
'foldignore' 设置项在 indent规则中以这个值开始的行的将根据前后行的值来设定折叠层级
:folddoclose 命令 对当前闭合的行运行命令
:folddoopen 命令 对未折叠的行或定义了折叠但未闭合的行运行命令
更多内容参考`:help vim-script‘
:help :folddoopen
:help :folddoclosed
3.
高效
1.移动速度
set hlsearch
*
使用fold 先全部关闭 移动到制定fold后再打开
2.Don't type it twice
使用CTR+n 自动填充 如果不对 则 CTR+p 回到起点 敲入新的字符 再 CTR+n时
3.Fix it when it's wrong
:iabbrev teh the
:syntax keyword WordError teh
4.A file seldom comes alone
:!ctags -R .
:tag init
:tnext
:grep “\<K_HOME\>” **/*.h
:cnext
:make
gf goto file
语法高亮帮助文档
:help syntax.txt
:help 'tags'
:help tags-file-format
:help tags-and-searches
:tag 关键字(跳转到与“关键字”匹配的标记处)
:tselect [关键字](显示与“关键字”匹配的标记列表,输入数字跳转到指定的标记)
:tjump [关键字](类似于“:tselect”,但当匹配项只有一个时直接跳转至标记处而不再显
示列表)
:tn(跳转到下一个匹配的标记处)
:tp(跳转到上一个匹配的标记处)
Ctrl-](跳转到与光标下的关键字匹配的标记处;除“关键字”直接从光标位置自动获得外,功
能与“:tags”相同)
g](与“Ctrl-]”功能类似,但使用的命令是“:tselect”)
g Ctrl-](与“Ctrl-]”功能类似,但使用的命令是“:tjump”)
首先,将当前文件中的所有a 变为but;
然后保存文件;
最后进入下一个文件缓存区。如果有多个文件需要如此处理,
使用函数
:s/__date__/\=strftime("%c")/ : 将__date__替换成当前日期,使用strftime
函数。注意\=表示后面是表达式,结果可能是2008-1-3 17:59:46
\=submatch(0) 匹配每行第一组数字
替换一个特定字符串为数字
:let i=10 | 'a,'bg/Abc/s/yy/\=i/ |let i=i+1 # 将yy转换成10,11,12 等等
比上面的更精确
:let i=10 | 'a,'bg/Abc/s/xx\zsyy\ze/\=i/ |let i=i+1 # 将xxyy 转换成 xx11(第
一行),xx12(第二行),xx13(第三行)
:%s:\(\(\w\+\s\+\)\{2}\)str1:\1str2:
处理字段,替换所有在第三个字段中的str1 为str2
交换两个单词
:%s/\<\(on\|off\)\>/\=strpart("offon", 3 * ("off" == submatch(0)), 3)/g
:%s/?\(.*\)\n\1$/\1/ delete duplicate lines
vim实现多文件查找和替换
对于多文件中的查找来说,比较容易,vimgrep是vim自带的一个工具,类似于
linux下的grep的用法就可以实现。比如要在当前目录查找word,
使用如下:
:vimgrep word *
如果想要递归查找所有下级目录里面,那么就用
:vimgrep word **
另外,如果想要在使用是快捷查找当前光标下的字母,则只需要在vimrc中添加如下代码:
“对搜索的设置
map ft :call Search_Word()<CR>:copen<CR>
function Search_Word()
let w = expand(”<cword>”) ” 在当前光标位置抓词
execute “vimgrep ” w ” *”
endfunction
第二,多文件替换。
实际上只要如下两个命令即可(假设要将当前目录下所有扩展名为.txt的文件中的hate
替换成love):
:args *.txt
:argdo %s/hate/love/gc | update
就可以完成啦。解释如下,
:args *.txt
这样写会扫描当前目录下的.txt文件,并加入到参数列表。但是这样写只会扫描当前目录,
如果想要递归扫描所有下级目录的话,用:args **/*.txt
而:argdo %s/hate/love/gc | update
是将参数列表中的所有文件的hate提换成love,并写入硬盘(如果没有|update,就不
会写入,但相应的替换也会被中断)
最后强调一点,使用替换命令的时候,一定记得备份,因为替换是直接写入硬盘滴哦……
专题:
1.模式行
:help modeline
:help 'modeline'
:help 'modelines'
模式一
// vim:ft=cpp tabstop=4
模式二
vim:set tw=78 ts=8 ft=help norl:sdfasdfasdgs
第一种形式中最后一设置项后的冒号或空格是可有可无的。
而第二种形式中最后一设置项后一定要有冒号——不管冒号后有没有文字。
在设置项中如果要使用空格、制表符或冒号可以在前面加上转义符-`\‘。
其他需要转义符的情况见`:help option-backslash‘。
2.折叠
:help folding
:help foldmethod
:help fold-methods
:help
:set foldmethod=manual
:3,8fo
折叠方式:
1)`manual‘ 手工规则
手工规则下,折叠层级由折叠区域的嵌套关系计算。当我们手工指定一个折叠的区域后,Vim
对这个区域的开始行和结束行做记号,多个区域的开始行和结束行形成了嵌套关系。如果一
个折叠区域不包含在其他区域之中,则其折叠层级为1;当这个区域直接包含于另一个区域
时则其为折叠层级为另一个区域的层级加1;依些类推。
2)`marker‘ 标记规则
当使用标记规则折叠时,层级的计算跟手工规则相似。除了它是根据文件中的标记来划分一
个折叠区域而不是手工指定。然后根据这些区域间的嵌套关系计算折叠层级。具体使用的标
记通过`foldmarker‘设置。默认是使用'{{{,}}}'。
手工和标记类似
:set foldmethod=manual
:3,8fo 或着高亮选择第三至8行 后 输入指令zf
使用manual一般是临时性的折叠。如果每次编辑特定文件都需要做同样折叠时时建议结合modeline使用其他折叠
规则。如果不得不使用manual方式时,你可以用:mksession保存包括折叠在内的一切当前编辑设置或者
用:mkview保存当前窗口
3)`indent‘ 缩进规则
行的缩进宽度除以`shiftwidth‘,并向下取整得到每一行的折叠层级。同一折叠层级及更高折
叠层级的连续行形成折叠。而其中的更高折叠层级的行——如果有的话,形成嵌套的折叠。
4)`syntax‘ 语法规则
跟`marker‘差不多,只是所用的标记是在语法文件中定义的,而不是通过`foldmarker‘设置。
5)`diff‘ 差异规则
除了差异行及其前 后三行1外,其余行折叠(层级为1)。
6)`expr‘ 表达式规则
由用户指定折叠层级的计算方式。方法是对`foldexpr‘进行设置。具体用法稍后说明。
:set foldmethod=expr
:set foldexpr=1
所有的行都被折叠 foldexpr将每行的折叠层级设置为1
v:lnum>=8&&v:lnum<=20?1:0
v:lnum>=8\ &&\ v:lnum<=20\ ?\ 1:0