正则表达式(二)——进阶之匹配分组

基础部分在这里:正则表达式(一)——基础之匹配字符,数量,边界

这部分我将换种形式来讲述,结合实际问题需求来讲述。

3.匹配分组

字符 功能
| 匹配左右任意一个表达式
(ab) 将括号中的字符作为一个分组
\num 引用分组num匹配到的字符串
(?P<name>) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串

1)| 

需求:匹配出0-100之间的数字

分析:首先我们明确这之间的数字包含0,两位数,100,,也就是一位,两位,三位的可能都有,鉴于一位0,三位100都是单独数字,我们可以使用 | 来连接(相当于or),着重考虑一位数[1-9],两位数[10-99],分析其特征,这里第一位数必须为[1-9],第二位[0-9]都可以(\d可以表示),对于一位数[1-9]的第二位可以不出现(?可以表示),再加个结尾$,防止234匹配到23的情况。因此正则表达式为:

r'[1-9]\d?$|0$|100$'
>>> re.match(r'[1-9]\d?$|0$|100$','08')
None
>>> re.match(r'[1-9]\d?$|0$|100$','0')
<_sre.SRE_Match object; span=(0, 1), match='0'>
>>> re.match(r'[1-9]\d?$|0$|100$','100')
<_sre.SRE_Match object; span=(0, 3), match='100'>
>>> re.match(r'[1-9]\d?$|0$|100$','101')
None
>>> re.match(r'[1-9]\d?$|0$|100$','80')
<_sre.SRE_Match object; span=(0, 2), match='80'>

我们再看下0能不能不用 | ,也把它包含进去?答案of course。想想 0 ,它是[1-9]不出现,第二位\d也不出现的情况,因此第一位[1-9]选择性出现用 ? ,因此正则表达式为:

r'[1-9]?\d?$|100$'
>>> re.match(r'[1-9]?\d?$|100$','0')
<_sre.SRE_Match object; span=(0, 1), match='0'>

这样的话,| 的功能是不是清楚了......

 2)(ab) 将括号中的字符作为一个分组

需求 :在网页开发或者爬虫时,处理对象是HTML,比如某网页HTML中有这样的内容:<h1>我的CSDN</h1>。那么我该如何把<h1>content</h1>中的content提取出来呢?

分析:提取的内容用()括起来就可以了。<h1> </h1>是固定标签,这是不变的,变的是content,因此我的正则表达式可表示为:

r'<h1>(.*)</h1>'
>>> re.match(r'<h1>(.*)</h1>','<h1>我的CSDN</h1>')
<_sre.SRE_Match object; span=(0, 15), match='<h1>我的CSDN</h1>'>

可以完美的匹配到了,问题还没解决,我怎么提取出来content呢。其实group()函数是可以接受参数的,其参数的意义是你的()个数的索引,比如你输入reslut.group(1)得到的是第一个括号的内容。reslut.group(0)是匹配到的所有内容,默认为0,所以你不输入,默认为0,返回匹配内容。Match Object还有个groups()函数,它返回的是所有括号的内容。如下所示:

>>> result = re.match(r'<h1>(.*)</h1>','<h1>我的CSDN</h1>')  #变量保存
>>> result.group()  #默认0,返回匹配内容
'<h1>我的CSDN</h1>'
>>> result.group(0) #输入0,返回匹配内容
'<h1>我的CSDN</h1>'
>>> result.group(1)  #返回第1个括号内容
'我的CSDN'
>>> result.groups()
('我的CSDN',)

我们看看两个括号的情况:

>>> result = re.match(r'<span>(\d+)</span><h1>(.*)</h1>','<span>1234</span><h1>我的CSDN</h1>')
>>> result
<_sre.SRE_Match object; span=(0, 32), match='<span>1234</span><h1>我的CSDN</h1>'>
>>> result.group(1)
'1234'
>>> result.group(2)
'我的CSDN'
>>> result.groups()
('1234', '我的CSDN')

所以说,()在网页开发,爬虫里还是挺重要的......学会它

 3)\num 引用分组num匹配到的字符串

需求 :还是以网页为例,比如判断某网页HTML格式是否正确,其中有内容:<html><h1>我的CSDN</h1></html>。这时,我们不关心里面的内容,我们关心的是格式是否正确,就是说这样的格式:<html>标签必须有</html>结束,<h1>标签必须有</h1>结束。

分析:这个时候像html和h1才是关键内容,如果我们把这些用()保存起来,并且在后面一定对应这些内容,就能保证标签的配对,而\num就是解决这样的问题的,上面group里面的参数index指的是第index个括号内容,\index即取得它的内容

1. 首先我们看个错误的样例:

>>> s = '<html><h1>my csdn</h1></html>'
>>> re.match(r'<.+><.+>.+</.+></.+>',s)   #关注html和h1这些内容, .+ 表示至少有内容
<_sre.SRE_Match object; span=(0, 29), match='<html><h1>my csdn</h1></html>'>
>>> s = '<html><h1>my csdn</h1></h>'    '''把s后面的html改成h,明显格式不对,但还是匹配了'''
>>> re.match(r'<.+><.+>.+</.+></.+>',s)
<_sre.SRE_Match object; span=(0, 26), match='<html><h1>my csdn</h1></h>'>

我们应该让第一个<tag>的内容出现在最后</tag>中,因此需要保存起来,用()括起来

2.正确的方法

我们应该把<tag>用()括起来,变成<(tag)>,因此正则表达式为:

r'<(.+)><(.+)>.+</\2></\1>'

解释下,这个\2 和 \1。这个就是我们上面groups()中的内容索引,可以拿到内容

>>> s = '<html><h1>my csdn</h1></h>'          #错误的标签格式
>>> re.match(r'<(.+)><(.+)>.+</\2></\1>',s)   #此时不符合了
None

>>> s = '<html><h1>my csdn</h1></html>'       #正确的标签格式
>>> result = re.match(r'<(.+)><(.+)>.+</\2></\1>',s)
>>> result
<_sre.SRE_Match object; span=(0, 29), match='<html><h1>my csdn</h1></html>'>
>>> result.groups()                     #那么 \2 指的是'h1' ; \1 指的是'html' 
('html', 'h1')

s = '<html><h1>my csdn</h1></html>

 result = re.match(r'<(?P<k1>.+)><(?P<k2>.+)>.+</(?P=k2)></(?P=k1)>',s)
>>> result
<_sre.SRE_Match object; span=(0, 29), match='<html><h1>my csdn</h1></html>

猜你喜欢

转载自blog.csdn.net/m0_37673307/article/details/81607986
今日推荐