6.2.1 正则表达式简介

正则表达式是用于文本匹配的工具,它在源字符串中查找与给定的正则表达式相匹配的部分。一个正则表达式是由字母、数字、汉字和特殊字符(括号、星号、问号等)组成的。正则表达式中有许多特殊的字符,这些特殊字符是构成正则表达式的要素。表6-4说明了正则表达式中特殊字符的含义。

表6-4 正则表达式中的特殊字符

其中,匹配符“[]”可以指定一个匹配范围,例如“[ok]”将匹配包含“o”或“k”的字符。同时“[]”可以与\w、\s、\d等标记等价。例如,[0-9a-zA-Z_]等价于\w,[^0-9]等价于\D。

注意 ^与[^m]中的“^”的含义并不相同,后者的“^”表示“除了……”的意思。

如果要匹配电话号码,需要形如“\d\d\d\d-\d\d\d\d\d\d\d”这样的正则表达式。其中出现了11次“\d”,表达方式烦琐。而且某些地区的电话号码是8位数字,区号也有可能是3位或4位数字,因此这个正则表达式就不能满足要求了。正则表达式作为一门小型的语言,还提供了对表达式的一部分进行重复处理的功能。例如,“*”可以对正则表达式的某个部分重复匹配多次。这种匹配符号称为限定符。表6-5列出了正则表达式中常用的限定符。

表6-5 正则表达式中的常用限定符

利用{}可以控制字符重复的次数。例如,\d{1,4}表示1~3位数字。前面提到的电话号码,可以采用如下的正则表达式。


\d{3}-\d{8} | \d{4}-\d{7}

【代码说明】该表达式匹配区号为3位的8位数电话号码或区号为4位的7位数电话号码。

在书写电话号码时,区号和本地号码之间采用“-”间隔,也有的在区号两侧加圆括号来分隔。这个需求也可以使用正则表达式实现。


[\( ]?\d{3}[\]-)?\d{8}|[\( ]?\d{4}[\]-]?\d{7}

【代码说明】“[\(-]?”表示最多只能取“(”或“-”其中之一,因此该表达式支持“-”或“()”两种分隔区号的方式,同时也支持把区号和本地电话号码连在一起书写,例如:010-12345678、01012345678、(010)12345678。

注意 “(”和“)”是正则表达式中的特殊字符,如果要把它们作为普通字符处理,需要在前面添加转义字符“\”。

如果要对正则表达式进行嵌套,就需要使用分组“()”。例如,对3位数字重复3次,可以使用如下的正则表达式表示。


(\d\d\d){2}

如果对字符串“123456789”进行匹配,则匹配到子串“123456”。如果正则表达式写为如下的形式,将匹配到不同的结果。


\d\d\d{2}

该表达式相当于“\d\d\d\d”,匹配的结果为“1234”和“5678”。

正则表达式的每个分组会自动拥有一个组号。从左往右第1个出现的圆括号为第1个分组,表示为“\1”;第2个出现的圆括号为第2个分组,表示为“\2”,以此类推。组号可以用于重复匹配某个分组。例如,对字符串“abc”重复匹配两次可以表示为如下的正则表达式。


(abc)\1

如果对字符串“abcabcab”进行匹配,则匹配的结果为“abcabc”。

默认情况下,正则表达式将匹配最长的字符串作为结果。可以通过在限定符后面添加“?”的方式,获取最短匹配的结果。例如,对字符“a”到字符“c”之间的字符进行匹配。


a.*c

如果对字符串“abcabc”进行匹配,则匹配结果为源字符串“abcabc”,即最长匹配。如果把正则表达式改为如下的方式,将进行最短匹配。


a.*?c

在“*”后添加了一个“?”,匹配结果为“abc”和“abc”。当匹配到第1个字符“c”后,匹配立刻中断,并返回匹配结果。然后继续进行新的匹配,即返回第2个“abc”。限定符与“?”组合还有一些其他的用法,如表6-6所示。

表6-6 限定符与?的组合

注意 表中的(?P<name>…)和(?P=name)是Python中的写法,其他的符号在各种编程语言中都是通用的。