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中的&,是作为字符串的连接符号.

这第一个命令的作用,就是找到等号,将等号前面的部分,用空格补齐到13个字符,
然后在等号后面空两格,等号后面原有的空格无论多少都去掉,然后把后面的内容,
到注释符号前面都整理成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;
注意三条语句,一旦某一条失败,则不执行下面的语句

:%s/a/but/gie|:update|:next :
首先,将当前文件中的所有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

三个在折叠的表达式比较常用几点:
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”)
Ctrl-T(跳转回上次使用以上命令跳转前的位置)