正则表达式

在 Vim 中最常用到正则表达式的莫过于搜索和替换命令。

先来看一个现实的问题,如果在 Vim 中,将正则表达式中定义的大量元字符原封不动地引用(就像 perl),势必会给使用正常编辑功能的人造成困扰。比如 /foo(1) 命令,按照正则表达式来理解会是搜索 foo1 字符串。而在大多数人编辑器中应该是搜索 foo(1) 字符串。

Vim 毕竟是一个编辑器,于是在 Vim 中规定,正则表达式的元字符必须用反斜杠进行转义(和大多数正则表达式对转义符的定义正好相反)。如果上面的例子要用正则表达式搜索,就应写成 /foo\(1\) 。但是,像 . * 这种极其常用的元字符,都加上反斜杠就太麻烦了。而且,众口难调,有些人喜欢用正则表达式,有些人不喜欢用...

为了解决这个问题,Vim 设置了 magic 变量。简单地说,magic 就是设置哪些元字符要加反斜杠哪些不用加的。 简单来说:

  • magic (\m):除了 $ . * ^ 之外其他元字符都要加反斜杠
  • nomagic (\M):除了 $ ^ 之外其他元字符都要加反斜杠

这个设置也可以在正则表达式中通过 \m \M 开关临时切换。 \m 后面的正则表达式会按照 magic 处理, \M 后面的正则表达式按照 nomagic 处理,并忽略实际的 magic 设置。

例如:

/\m.*   # 查找任意字符串
/\M.*   # 查找字符串 .* (点号后面跟个星号)

另外还有两个包含全部的命令。

  • \v (即 very magic):任何元字符都不用加反斜杠
  • \V (即 very nomagic):任何元字符都必须加反斜杠

例如:

/\v(a.c){3}$      # 查找行尾的 abcaccadc
/\m(a.c){3}$      # 查找行尾的 (abc){3}
/\M(a.c){3}$      # 查找行尾的 (a.c){3}
/\V(a.c){3}$      # 查找任意位置的 (a.c){3}$

Vim 默认设置是 magic,也推荐大家都使用 magic 的设置。有特殊需求时,直接通过 \v \m \M \V 中的一种定义即可。

Vim 中设定 magic 变量:

:set magic     " 设置magic
:set nomagic   " 取消magic
:h magic       " 查看帮助

基本元素

本文下面使用的字符都是默认(magic)模式下的,在其他模式下请自行转义。

常用的元字符

元字符 意义
. 匹配任意一个字符
[abc] 匹配方括号中的任意一个字符。也可以用 - 表示范围
[a-z0-9] 匹配小写字母和阿拉伯数字中的一个字符
[^abc] 匹配除方括号中字符之外的任意一个字符
\(abc\) 分组匹配,将 abc 放入 1 中
\d 匹配阿拉伯数字,等同于 [0-9]
\D 匹配阿拉伯数字之外的任意字符,等同于 [^0-9]
\x 匹配十六进制数字,等同于 [0-9A-Fa-f]
\w 匹配单词字母,等同于 [0-9A-Za-z_]
\W 匹配除单词字母之外的任意字符,等同于 [^0-9A-Za-z_]
\t 匹配 <TAB> 字符
\s 匹配空白字符,等同于 [ \t]
\S 匹配非空白字符,等同于 [^ \t]
\a 匹配所有的字母字符。等同于 [a-zA-Z]
\l 匹配小写字母 [a-z]
\L 匹配非小写字母 [^a-z]
\u 匹配大写字母 [A-Z]
\U 匹配非大写字幕 [^A-Z]

注解

\(\) 进行分组匹配,在分组后面可以使用 \1\2 等变量来访问分组的内容(注意:\0 表示匹配的所有内容),最多保存一行中的 9 个分组。这种形式实际上是将分组中的内容保存到特殊的空间(保留缓冲区)中。

# 原字符串 That or this
# 替换后的字符串 this or That

:%s/\(That\) or \(this\)/\2 or \1/

量词

元字符 意义
* 匹配 0 个或多个
\+ 匹配1个或多个(匹配优先)
\? 或 \= 0 个或 1 个,\? 不能在 ? 命令中使用
\{n,m} 匹配 n 个到 m 个
\{n,} 匹配最少 n 个
\{,m} 匹配最多 m 个
\{n} 匹配 n 个

注解

用于限定数量的元字符不仅可用于字符,也可以用于分组等模式。举例如下:

\(123\)\{2}   # 匹配 123123

表示位置的符号

元字符 意义
$ 匹配行尾,如 tail$ 只匹配位于一行结尾处的 tail
^ 匹配行首,如 ^head 只匹配位于一行开头处的 head
\< 匹配以某些字符开头的单词,\<ac 只匹配以 ac 开头的单词,如 action
\> 匹配以某些字符结尾的单词,ad\> 只匹配以 ac 开头的单词,如 head

非贪婪匹配

正则表达式中有贪婪匹配和非贪婪匹配两种,Vim 默认开启贪婪匹配。如果想使用非贪婪匹配,可以使用 \{-} 代替 *+ 等量词。

字符串:ahdbjkbkls

a.*b       # 匹配 ahdbjkb
a.\{-}b    # 匹配 ahdb