一、前言
当我们想以特定的规则从字符串中匹配出想要的子串时,正则表达式非常有用。而且,大部分编程语言都集成了正则表达式,我们学会它的语法规则后,可以直接在各种编程语言中运用。
正则表达式大致有以下应用:
- 数据验证(例如:检查时间字符串是否格式正确)
- 数据抓取(例如:网页抓取,以特定顺序查找包含特定单词集的所有页面)
- 数据整理(例如:将原始数据转换为另一种格式)
- 字符串解析(例如:捕获所有 URL GET 参数,捕获一组括号内的文本)
- 字符串替换、语法高亮、文件重命名、数据包嗅探
在实际场景中,被匹配的字符串内容杂乱无章,但稍加分析,会发现其实质要么是 ASCII
码,要么就是实现了 unicode
的各种编码。unicode
兼容 ASCII
,而这些编码有个特点,在特定的二进制范围中表示的字符有着相同的特性。比如 ASCII
中的 0-31
位表示一些控制字符,32-127
位则是一些可打印出来的字符,不一而足。
由此不难想见,我们可以针对不同类别字符的特性,制定一些规则。而正则表达式正是使用一些特殊的元字符构造出了自己的一套匹配规则,从而匹配出任意形式的数据。这些元字符本来没有什么特殊,但经过正则表达式引擎的编译,便具有了特殊的功能,看似不知所云,但实际记录了很多的信息。
正则通常用 //
包裹,后面跟上若干个匹配标志,比如:/a[bc]+/gm
。
一个正则表达式,大致遵循这样的编写思路:什么位置,什么样的关键词,有几个,怎么做,那么上面的这个正则可以这样解读:「以全局、多行的模式匹配出任意位置的这样一个字符串:a
后面跟着一个或多个 b
或 c
」。
下面按照这个思路分层次讲解,其中给出的用例可以使用这个工具测试。
二、编写思路
1. 什么位置
1.1 关键词位于行开头(^
)或行结尾($
)
^
习惯上读作 Cat
,$
读作 Dollar
。
正则表达式 | 含义说明 |
---|---|
ok |
匹配字符串 ok 。 |
^ok |
匹配字符串 ok ,而且 ok 前面是行开头。 |
ok$ |
匹配字符串 ok ,而且 ok 后面是行结尾。 |
^ok$ |
匹配字符串 ok ,而且 ok 前面是行开头,ok 后面是行结尾。 |
1.2 指定关键词前后的字符内容 (?=)
和 (?<=)
正则表达式 | 含义说明 |
---|---|
(?<=r)ok |
ok 前面是 r ,结果不捕获 r 。 |
ok(?=r) |
ok 后面是 r ,结果不捕获 r 。 |
这里可以将 =
替换为 !
,表示否定。
正则表达式 | 含义说明 |
---|---|
ok(?!r) |
ok 后面不是 r ,但结果不捕获 r 。 |
(?<!r)ok |
ok 前面不是 r ,但结果不捕获 r 。 |
2. 什么样的关键词
2.1 单字符关键词
2.1.1 限定单字符关键词的备选值:用 []
包裹
正则表达式 | 含义说明 |
---|---|
[abc] |
包含 abc 中的一个,等价于 a|b|c 。 |
[a-c] |
同上。 |
[a-fA-F0-9] |
单个十六进制数字的字符串,且不区分大小写。 |
[0-9]% |
% 前面是一个数字。 |
[^a-zA-Z] |
不在 a~Z 的范围内。在这个例子中,^ 表示否定。 |
2.1.2 元字符转义
看到这里,我们知道 ^$<>()[]{}|/.+*?:=!
这些元字符在正则中可能有着特殊的作用。那么这里会有个问题,正则表达式是用字符串来描述匹配规则,进而去匹配字符串。如果我们需要匹配这些元字符本身该怎么办呢?
这时可以在这些字符前添加转义符号 ,使其还原为字符本身,不再具备限定含义。
正则表达式 | 含义说明 |
---|---|
$d |
$ 后面跟着一个数字字符。 |
2.2 多字符关键词
2.2.1 构造关键词元组:用 ()
包裹
之前的例子中,只能对单字符关键词进行限定,如果要对多字符关键词进行限定,可以用 ()
括起来,构造成一个关键词元组,看下面的例子。
正则表达式 | 含义说明 |
---|---|
a(bc) |
a 后面跟着一个 bc 。 |
a(?:bc)* |
a 后面不能跟着一个 bc 。 |
a(?<foo>bc) |
a 后面跟着一个 bc ,并将 bc 这个元组命名为 foo 。 |
当我们自己的编程语言从字符串或文本数据中匹配信息时,像这样构造关键词元组非常有用。这样的匹配结果会返回一个列表,从而方便我们根据下标去取值。
而如果使用的是上表的第三种,给关键词元组命名的方式,返回的结果则是字典。键的名称是组名 foo
,值是匹配结果列表。
2.2.2 引用关键词元组:1
正则表达式 | 含义说明 |
---|---|
([abc])1 |
引用第一个关键词元组 ([abc]) 匹配的相同文本。 |
([abc])([de])21 |
2 引用第二个关键词元组 ([de]) 匹配的相同文本。 |
(?<foo>[abc])k<foo> |
k<foo> 引用前面名为 foo 的关键词元组 (?<foo>[abc]) 匹配的相同文本。结果与 ([abc])1 相同。 |
2.3 特定类型关键词
正则表达式 | 含义说明 |
---|---|
. |
匹配任意字符,当匹配标志不是 s 时,不匹配 n 。 |
d |
匹配数字。 |
D |
匹配非数字。 |
b |
表示它的一边是单词字符,一边不是单词字符。如 bokb ,ok 前面是 n 、空格 这样的非单词字符,后面也是非单词字符。 |
B |
匹配 b 所有不匹配的内容。如 BokB ,ok 前面是单词字符,后面也是单词字符。 |
w |
匹配字母、数字、下划线。 |
W |
匹配非字母、非数字、非下划线。 |
s |
匹配空白字符,包括空格( )、水平制表符(t )、换行符(n )、换页符(f )、回车符(r )、垂直制表符(v )、空字符(
|