Vim 的查找命令(即搜索命令)、Vim 替换命令 (substitute 命令) 和 Vim 的 global 命令均支持通过正则表达式指定搜索模式pattern。Vim根据 pattern 来匹配文本,也可通过 pattern 来指定 Vim 命令的操作对象。

本文(原创自Vim教程网(https://vimjc.com)简单总结下正则表达式的入门内容并介绍其在 Vim 命令中的应用。

一、正则表达式元字符

元字符(meta character)是正则表达式语法中具有特殊含义的保留字符(专用字符),用于描述位于元字符前面的字符在待匹配对象中的出现模式。重要的正则表达式元字符主要可以归为以下几类。

1.1 表示【目标字符集】的元字符

正则表达式中,列举目标字符集需要用到 [] 元字符。为了方便描述,以 abcd 作为目标字符集作为举例说明。

[abcd]      表示匹配方括号中列举的 任意一个 字符,即匹配 abcd 中的任意一个字符。
                     可用 - 表示字符范围来减少列举的,例如,[a-d] 等价于 [abcd]
[^abcd]    表示匹配除 方括号中字符以外 的任意字符。

为了使用上的便利,正则表达式中保留定义了一些常用的字符集合,主要包括:

.                等价于 [^\n],表示匹配 任意一个除换行符 ( \n ) 外的其他字符

\l              等价于 [a-z],表示匹配 任意一个小写字母
\L              等价于 [^a-z],表示匹配 任意一个除小写字母外的其他字符
\u              等价于 [A-Z],表示匹配 任意一个大写字母
\U              等价于 [^A-Z],表示匹配 任意一个除大写字母外的其他字符

\w              等价于 [0-9A-Za-z_],表示匹配 任意一个单词字母
\W              等价于 [^0-9A-Za-z_],表示匹配 任意一个除单词字母外的其他字符

\d              等价于 [0-9],表示匹配 任意一个阿拉伯数字
\D              等价于 [^0-9],表示匹配 任意一个除阿拉伯数字外的其他字符
\x              等价于 [0-9A-Fa-f],表示匹配 任意一个十六进制数字
\X              等价于 [^0-9A-Fa-f],表示匹配 任意一个除十六进制数字外的其他字符

:上面这些保留定义都用到了转义元字符 \。因为 ludx 这些都是普通字母,只有加上转义字符才有上述特殊含义。

1.2 表示【次数】的元字符

如果希望指定一个目标字符在匹配结果中同时出现多次,那么需要用到正则表达式中表示 次数 的元字符,主要包括:

*                表示匹配 0个或者任意个目标字符
\+              表示匹配 1个或者任意个目标字符
\?              表示匹配 0个或者1个目标字符

\{n,m}      表示匹配 n-m 个目标字符,即最少匹配 n 个目标字符,最多匹配 (m-1) 个目标字符。
\{n}          表示匹配 n 个目标字符 (即目标字符需连续出现 n 次)。
\{n,}        表示匹配 n-任意个目标字符,即最少匹配 n 个目标字符。
\{,m}        表示匹配 0-m个目标字符,即最多匹配 (m-1) 个目标字符,也可以不匹配 (0)。

1.3 表示【位置】的元字符

如果希望指定目标字符出现的位置,可以使用正则表达式中表示 位置 的元字符,主要包括:

^                表示匹配 输入字符串的开始位置 (行首)
$                表示匹配 输入字符串的结束位置 (行尾)
\<              表示匹配 单词词首
\>              表示匹配 单词词尾

1.4 表示【子模式】的元字符

元字符 () 用来标识一个子模式,任何 () 内部的匹配文本被称作为一个 子匹配,都会被自动保存到一个临时的仓库中以便后续进行引用。

可以用 \1\2 …… \9 来依次引用被每对 () 捕获的子匹配;不论模式中是否使用了 (),元字符 \0 永远会自动引用于整个匹配。

1.5 表示【非打印字符】的元字符

正则表达式中比较常用的非打印元字符主要包括:

\n              表示匹配 一个换行符
\r              表示匹配 一个回车符
\t              表示匹配 一个制表符 ( Tab 键)
\s              表示匹配 任意一个空白字符,包括空格、制表符、换页符等。
\S              表示匹配 任意一个非空白字符

二、正则表达式在Vim查找命令中的应用

如《Vim查找命令使用方法》一文所介绍,在 Vim 的普通模式下,输入 /? 符号就进入了搜索模式,可用于实现正向或反向搜索目标字符串。

假设当前光标所在单词为 target,如果要从当前光标所在位置往下搜索单词 target 出现的所有位置,则可以使用命令 /\<target\>。这里便用到了表示位置的元字符 \<\>。为了简化操作,可以在 Vim 的普通模式下按 * 可实现同样的效果,但是其原理与直接输入 /\<target\> 进行查找完全等价 (可以观察到,按下 * 键后,Vim 会自动进入搜索模式,并将当前光标所在的单词作为搜索目标)。操作结果如下图所示。

Vim正则表达式查找

如果希望搜索所有以 // 开头的行,可以执行 /^\/\/.*$ 命令。这里便用到了表示行首和行尾的元字符 ^$,以及表示任意一个非换行符外的元字符 . 和表示字符出现次数的元字符 *。操作结果如下图所示。

Vim正则表达式查找

如果希望搜索所有的空行,可以使用 /^$ 命令,操作结果如下图所示。

Vim正则表达式查找

Vim 对基于正则表达式的查找进行了额外的支持,包括 magic 搜索模式和 very magic搜索模式等,也包括使用元字符 \zs\ze 对匹配进行裁剪等。推荐阅读《Vim搜索字符转义与very magic搜索模式》获取更多细节。

三、正则表达式在Vim替换命令substitute中的应用

Vim替换命令 substitute (缩写形式 s) 的基本语法是 :[range]substitute/源字符串/目标字符串/[option],其中rangeoption字段都可以缺省不填。

而上述语法描述中的源字符串便可以通过正则表达式指定。

例如,可通过 :%s/\s*$//g 命令删除 Vim 当前打开文件中的所有行尾空格 (为什么 :%s/\s+$//g 不行?求解释)。这里的源字符串通过正则表达式 \s*$ 进行指定,表示以 0 个或多个空格结尾。操作结果如下图所示

Vim正则表达式替换

同样地,可通过 :%s/^\s*//g 命令删除 Vim 当前打开文件中的所有行首空格,操作结果如下图所示。

Vim正则表达式替换

可通过命令 :%s/^/\/\// 在全文范围内,在所有的行首加入 // ,达到注释当前文件所有代码的效果,操作结果如下图所示。

Vim正则表达式添加注释

四、正则表达式在Vim global命令中的应用

Vim 命令行模式下的 global命令 (缩写形式 :g) 可用于在某个指定模式的所有匹配行上运行可执行的 Ex 命令,这里提到的指定模式便可以使用正则表达式。

例如,可以在 Vim 中执行命令 :g/^\s*$/d 来删除 Vim 当前打开文件中的所有空白行,操作结果如下图所示。

Vim正则表达式删除空白行

如果要删除以 // 开头的所有行,可以执行命令 :g/^\/\/.*$/d,操作结果如下图所示。

Vim正则表达式删除注释行

《女程序员说》

原创不易,希望能给小女子的公众号加个关注~