* 指前面所出现的字元或字元集合,出现0或0次以上;
\+ 匹配内容同上,只不过出现次数不包括0次;
\= 指前面所出现的字元,仅出现0次或者1次;
\| 这个是多选,同or的意思相同,无论满足哪个条件都可以匹配;
\{n,m} 指前面所出现的字元或字元集合最少出现n次,最多出现m次;
上面这个可以演变一下几种,
\{n} 指前面所出现的字元或字元集合出现次数为n次;
\{n,} 指前面所出现的字元或字元集合最少出现为n次;
\{,m} 指前面所出现的字元或字元集合最多出现为m次;
^ 匹配行首,在这个后面的字元出现在行首才符合;
$ 匹配行尾,在这个之前的字元出现在行尾才符合;
[...] 字元集合,表示符合括号中所有字元中的其中一个;
[^...] 上面这个的补集,表非括号中字元的其中一个;
. 代表除换行字外的任一单一字元;千万不要小看了它,天大的符号(某网友语)自然不一般,在VIM的normal模式下,它可以重复上次的命令;在这边又可以表示任一字元,果然名不虚传;
讲了这么多来点实际的例子。
写elan单片机程序时,程序的标号都必须顶在最前,而且后面有个":",如果忘记打了这个":"怎么办?一个一个找,再加上,当然也是可以。如果用VIM,就不用那么麻烦了。对了,用VIM的替代然后加上强大的正则表达式。看看VIM的神奇吧,敲入
:%s/^[a-zA-Z].*[^:]$/&:/gc
^[a-zA-Z]表示匹配行首为字母,可以排除不是顶在最前的其它指令,还可以排除顶在最前面的注释,因为注释使用";"打头,不在范围之内。
[^:]$表示匹配行尾不是以":"结尾的东东。然后那个".*"就表示中间任意字元都行。这样只要行首和行尾符合的都会在后面加上":"了。怎么样,好用吧!
其实关于那个[a-zA-Z]在VIM中有简单的表示方法,再来看看正则表达式中的一些简写
\s 表示空白字元,即 Space 或 Tab 。
\S 表示非空白字元
\d 表示数字,即[0-9]。
\D 表示非数字,即[^0-9]。
\w 表示一般字元,包括下划线。即[0-9a-zA-Z_]。
\W 表示非一般字元,即[^0-9a-zA-Z]。
\a 表示英文字母,即[a-zA-Z]。
\A 表示非英文字母,即[^a-zA-Z]。
\l 表示小写字母,即[a-z]。
\L 表示非小写字母,即[^a-z]。
\u 表示大写字母,即[A-Z]。
\U 表示非大写字母,即[^A-Z]。
看完了上面的这些简写表示,上面那个例子其实可以改写如下:
:%s/^\a.*[^:]$/&:/gc
可以达到同样的效果。
再来一个例子,写程序时难免会在某些行尾会留下一些多余的空格或者TAB指令,虽然没什么影响,但用VIM同样可以轻松找到这些多余的空指令,并删除。看看下面这个指令:
:%s/\s$//gc
试用一下,好像不错,末尾的空白指令都被删除了!但是仔细去看如果行尾有不止一个的空白指令,上面那个就只会取代最后一个空白指令,而忽略其它的空白指令。让我们动手再改进一下!用到前面的\+,这样就基本上ok了!不管行尾有多少空白指令都可以匹配到了!
:%s/\s\+$//gc
量词
vim的量词与perl相比一点也不逊色。
vim | Perl | 意义 |
* | * | 0个或多个(匹配优先) |
\+ | + | 1个或多个(匹配优先) |
\? 或 \= | ? | 0个或1个(匹配优先),\?不能在 ? 命令(逆向查找)中使用 |
\{n,m} | {n,m} | n个到m个(匹配优先) |
\{n,} | {n,} | 最少n个(匹配优先) |
\{,m} | {,m} | 最多m个(匹配优先) |
\{n} | {n} | 恰好n个 |
\{-n,m} | {n,m}? | n个到m个(忽略优先) |
\{-} | *? | 0个或多个(忽略优先) |
\{-1,} | +? | 1个或多个(忽略优先) |
\{-,1} | ?? | 0个或1个(忽略优先) |
从上表中可见,vim的忽略优先量词不像perl的 *? +? ?? 那样,而是统一使用 \{- 实现的。这大概跟忽略优先量词不常用有关吧。
环视和固化分组
vim居然还支持环视和固化分组的功能,强大,赞一个。关于环视的解释请参考Yurii的《精通正则表达式》一书吧。
vim | Perl | 意义 |
\@= | (?= | 顺序环视 |
\@! | (?! | 顺序否定环视 |
\@<= | (?<= | 逆序环视 |
\@<! | (?<! | 逆序否定环视 |
\@> | (?> | 固化分组 |
\%(atom\) | (?: | 非捕获型括号 |
和perl稍有不同的是,vim中的环视和固化分组的模式的位置与perl不同。例如,查找紧跟在 foo 之后的 bar,perl将模式写在环视的括号内,而vim将模式写在环视的元字符之前。