新浪博客

vim中查找不包含特定字符串的行

2016-06-25 00:33阅读:
在vim中如果要为某种特定文件类型写一个语法高亮的插件(类似于syntax目录下的c.vim文件),少不了要用到正则表达式.
例如匹配不含特定字符串的行:匹配所有不包含'include'字符串的行.这需要用到正则表达式的 '零宽断言'(zero-width),vim帮助文档中的解释是:
vim中查找不包含特定字符串的行图1
简单介绍如下:
\@=: foo\(bar\)\@=
这条正则表达式的含义是:匹配那些前3个字符为'foo'且紧跟着字符串'bar'的'foo',示例如下:
vim中查找不包含特定字符串的行图2
图中高亮部分即为匹配结果,可见'foobar'与'foobarfoo'均匹配成功.倘若正则表达式为
foo\(bar\)\@=foo,能否匹配'foobarfoo' ? 结果如下:
vim中查找不包含特定字符串的行图3
3个字符串均未匹配成功!!!这就是'零宽断言'的特性,它仅仅是检查能否匹配而不会包含匹配的字符,简单来说就是foo\(bar\)\@=只是检测是否存在以'foo'开头紧跟着'bar'的字符串,根据之前的结果可知'foobar'、'foobarfoo'均满足,但是实际匹配到的字符串只是'foo'而不是'foobar'(仔细理解'零宽'zero-width的含义),那自然不存在'foofoo'这样的字符(foo\(bar\)\@=foo).
\@!: foo\(bar\)\@!
这条正则的含义是:任何以'foo'开头且后面不是'bar'的'foo'.
现在回到正题,要查找不含'include'字符串的行,显然要借助 '\@!',很容易想到
\(include\)\@! ,让我们来看看实际效果:
vim中查找不包含特定字符串的行图4
从结果看来,该正则表达式只是忽略了所有字符'i',而其他部分都认为是符合规则的匹配.让我们来分析下 \(include\)\@!,看看缺了什么.首先 \(include\) 表示匹配字符串'include',很显然,1、2、4行中的include均会被匹配,那么加上 \@! 表示什么意思呢?回过头在看下vim中 \@! 的解释:
vim中查找不包含特定字符串的行图5
很显然: if the preceding atom does NOT match at the current position. 除了在'include'的字符'i'这里之外,其他任何地方都不会匹配,故结果才如图4所示.我们需要对 \(include\)\@! 进行修改.为了达到匹配不包含字符串'include'的行,我们需要进行如下工作:
(1)匹配所有的行
(2)行中不能存在字符串'include'
将以上要求翻译为正则表达式如下:
(1)^.* ('^':表示某行的开头, '.':表示除了换行符外的所有字符, '*':用来修饰字符'.',表示匹配0次或多次)
(2)\(include\)\@!
自然而然的想到或许 ^.*\(include\)\@! 能满足要求,让我们来看看实际结果:
vim中查找不包含特定字符串的行图6
所有行全部被匹配!!!!为什么会这样呢?关键就在于 ^.* 这个正则表达式是贪婪的,它会一直匹配到行尾.
继续分析第(2)个要求,行中不能存在字符串'include',实际就是行中的任何字符后都不能出现'include',所以第二个表达式应该写成: \(.*include\)\@!, 让我们分析下这个表达式:
(1)\(.*include\): 表示匹配以任意字符开头(除换行符外)且后面出现'include'
那么到此我们想要匹配不含有字符串 'include'的行的正则表达式可以写为:
^\(.*include\)\@!.*
实际验证结果如下:

vim中查找不包含特定字符串的行图7


​​​​​​​

​​​​​​
​​​

我的更多文章

下载客户端阅读体验更佳

APP专享