python正则表达式精讲--分组

1. 什么是分组

分组是用圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组。使用分组,可以从目标字符串中提取出与圆括号内正则表达式相匹配的内容。

import re

string = "现在是北京时间12点10分"
pattern = re.compile(r'\D*(\d{1,2})\D*(\d{1,2})\D*')
result = pattern.match(string)
print(result.groups())

\D 是非数字字符,正则表达式里有两个分组,可以从目标字符串中提取出小时和分钟,程序输出结果为

('12', '10')

2. 定义分组的3种形式

有3种形式的分组:

  1. (exp) :把括号内的正则作为一个分组,系统自动分配组号,可以通过分组号引用该分组
  2. (?Pexp) :定义一个命名分组,分组的正则是exp,系统为该分组分配分组号,可以通过分组名或分组号引用该分组
  3. (?:exp) :定义一个不捕获分组,该分组只在当前位置匹配文本,在该分组之后,无法引用该分组,因为该分组没有分组名,没有分组号,也不会占用分组编号

在第1小节中,已经向你展示了第一种分组的形式,现在来看一个命名分组的例子

2.1 命名分组

命名分组也使用圆括号,在正则表达式前面添加一个命名的步骤,以?P开头,在<>内填入分组的名称

import re

string = "现在是北京时间12点10分"
pattern = re.compile(r'\D*(?P<hour>\d{1,2})\D*(?P<minute>\d{1,2})\D*')
result = pattern.match(string)
print(result.groupdict())

使用了命名分组,就可以使用groupdict方法来获得match的结果,是一个字典

{'hour': '12', 'minute': '10'}

2.2 不捕获分组

使用不捕获分组,括号内的内容不会被捕获到

import re

string = "现在是北京时间12点10分"
pattern = re.compile(r'\D*(?:\d{1,2})\D*(?:\d{1,2})\D*')
result = pattern.match(string)
print(result.group())
print(result.groups())
print(result.groupdict())

程序输出结果

现在是北京时间12点10分
()
{}

正则表达式的确在目标字符串中找到了模式,因此group()返回的是匹配到的内容,尽管两个分组也匹配到了内容,但由于是使用的是不捕获分组,因此圆括号里的内容不会被捕获,groups()返回的是空元组。

根据前面3个例子,可以做出一张反应分组形式与获取结果方法之间的关系表

普通分组(exp) 命名分组(?Pexp) 不捕获分组 (?:exp)
group 返回匹配的内容 返回匹配的内容 返回匹配的内容
groups 以元组形式返回匹配到的分组内容 以元组形式返回匹配到的分组内容 空元组
groupdict 空字典 以字典形式返回匹配到的分组内容 空字典

3. 引用分组

引用分组的目的是对重复出现的文本进行匹配,这里极容易产生误解,理解成对重复的模式进行匹配,其实,是对重复的文本进行匹配。

3.1 分组编号

对于普通分组,正则表达式引擎会默认为它们分配一个编号,从1开始,在编写整个表达式时,后面的部分可以通过编号引用前面的分组

import re

string = "现在是北京时间12点12分"
pattern = re.compile(r'\D*(\d{1,2})\D*\1\D*')
result = pattern.match(string)
print(result.groups())      # ('12',)

上面的例子中,只有一个分组(\d{1,2}),它的编号是1,在表达式的后半部分,使用\1 来复用分组1,你可能会以为,例子中的正则等价于

r'\D*(\d{1,2})\D*(\d{1,2})\D*'

这样理解是错误的,如果你将时间改为“12点13分”, 上面的例子就无法正常运行了,原因在于引用分组是对重复出现的文本进行匹配,而不是对重复出现的模式进行匹配。虽然13可以匹配\d{1,2},但与分组1匹配到的12不相同,因此整个表达式不能匹配目标字符串。

3.2 分组命名

对于命名分组,没有分组编号,而是用分组的名字,命名分组的形式是(?Pexp), 在引用时,则使用(?P=name),和引用分组编号一样,它只能对重复的文本进行匹配,而不是对重复的模式进行匹配。

3.3 不捕获分组

对于不捕获分组,既没有分组编号,也没有分组名称,因此无法引用不捕获分组

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案