分组,即分组匹配,也称为捕获组,是正则中的一种比较重要的匹配方式。此外后向引用和分组相结合,可以写出很多复杂匹配场景的正则。

1. 分组

分组的方法:将子表达式用小括号括起来,如:(exp),表示匹配表达式exp,并捕获文本到自动命名的组里。举例:

import re
s = 'c1c b2b c3c'
p = re.compile(r'c(\d)c')
print '【Output】'
print re.findall(p,s)
【Output】
['1', '3']
s = 'a1b2 c3d4 ea7f'
p1 = re.compile(r'[a-z]\d[a-z]\d') print '【Output 1】'
print re.findall(p1,s) p2 = re.compile(r'[a-z]\d[a-z](\d)') print '\n【Output 2】'
print re.findall(p2,s) p3 = re.compile(r'[a-z](\d)[a-z](\d)') print '\n【Output 3】'
print re.findall(p3,s)
【Output 1】
['a1b2', 'c3d4'] 【Output 2】
['2', '4'] 【Output 3】
[('1', '2'), ('3', '4')]
s = 'age:13,name:Tom;age:18,name:John'
p = re.compile(r'age:(\d+),name:(\w+)')
it = re.finditer(p,s)
print '【Output】'
for m in it:
print '------'
print m.group()
print m.group(0)
print m.group(1)
print m.group(2)
【Output】
------
age:13,name:Tom
age:13,name:Tom
13
Tom
------
age:18,name:John
age:18,name:John
18
John

2. 忽略某个分组

有时候给正则的某个子表达式加括号并不是为了分组,而仅仅是为了看起来更清晰,因此在匹配结果中并不想匹配该子表达式,那么该怎么办呢?答案是忽略该分组,方法:(?:exp)。举例:只想匹配name,不想匹配age:

s = 'age:13,name:Tom'
p1 = re.compile(r'age:(\d+),name:(\w+)')
print '【Output】'
# 不忽略分组
print re.findall(p1,s) # 忽略分组
p2 = re.compile(r'age:(?:\d+),name:(\w+)')
print re.findall(p2,s)
【Output】
[('13', 'Tom')]
['Tom']

3. 后向引用

所谓后向引用,就是对前面出现过的分组再一次引用,使用默认的分组名称进行后向引用:\1,\2,\3...(注:从1开始)

举例:

# 匹配字符串中连续出现的两个相同的单词
s = 'hello blue go go hello'
p = re.compile(r'\b(\w+)\b\s+\1\b') # 这里的'\1'就对应前面的(\w+)
print '【Output】'
print re.findall(p,s)
【Output】
['go']

4. 自定义名称分组的后向引用

python正则可以对分组自定义名称,然后可以使用自定义名称进行后向引用,使用自定义分组名称比使用默认分组名称更加清晰、更容易让人理解。对分组自定义名称的方法:

(?P<myname>exp)

后向引用的方式:

(?P=myname)

这里要注意的是,其他语言的正则与python正则的分组自定义名称的语法不太一样,其他语言是这样写的:

# 自定义名称
(?<name>exp)
# 后向引用
\K<name>

举个例子:

s = 'hello blue go go hello'
p = re.compile(r'\b(?P<my_group1>\w+)\b\s+(?P=my_group1)\b')
print '【Output】'
print re.findall(p,s)
【Output】
['go']

5.嵌套分组

s  = '2017-07-10 20:00'
p = re.compile(r'(((\d{4})-\d{2})-\d{2}) (\d{2}):(\d{2})')
re.findall(p,s)
# 输出:
# [('2017-07-10','2017-07','2017','20','00')] se = re.search(p,s)
print se.group()
print se.group(0)
print se.group(1)
print se.group(2)
print se.group(3)
print se.group(4)
print se.group(5) # 输出:
'''
'2017-07-10 20:00'
'2017-07-10 20:00'
'2017-07-10'
'2017-07'
'2017'
'20'
'00'
'''

可以看出,分组的序号是以左小括号'('从左到右的顺序为准的。

6. 后向引用的应用

1. 匹配"ABAB"型字符串

s = 'abab cdcd efek'
p = re.compile(r'(\w\w)\1')
print '【Output】'
print re.findall(p,s)
【Output】
['ab', 'cd']

2. 匹配"AABB"型字符串

s = 'abab cdcd xxyy'
p = re.compile(r'(\w)\1(\w)\2')
print '【Output】'
print re.findall(p,s)
【Output】
[('x', 'y')]

3. 匹配"AABA"型字符串

s = 'abab cdcd xxyx'
p = re.compile(r'(\w)\1(?:\w)\1')
print '【Output】'
print re.findall(p,s)
【Output】
['x']

4. 匹配"ABBA"型字符串

s = 'abab toot'
p = re.compile(r'(\w)(\w)\2\1')
print '【Output】'
print re.findall(p,s)
【Output】
[('t', 'o')]

5. 向字符串中的某些位置插入字符

有一个需求:在一个字符串中的所有通配符(% _ [ ])前都加上"\"符进行转义,如果通配符前面本来就有"\",则不再插入。举例:

s = 'abc\\_de%fgh[c][]c'
special = r'[%_\[\]]'
print '【Output】'
print 's = {0}'.format(s)
print re.sub(r'([^\\])(?=%s)' % special,r'\1\\',s)
# 注:这里的"(?=%s)"是零宽断言,匹配一个位置,零宽断言在后面会讲
【Output】
s = abc\_de%fgh[c][]c
abc\_de\%fgh\[c\]\[\]c

6. 在字符串中从后往前每隔3个字符插入一个","符号

s = '1234567890'
s = s[::-1]
print '【Output】'
print s
s = re.sub(r'(...)',r'\1,',s)
print s[::-1]
【Output】
0987654321
1,234,567,890

随机推荐

  1. 【BZOJ】3296: [USACO2011 Open] Learning Languages(tarjan)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3296 显然,每群能交流的群是个强联通块 然后求出scc的数量,答案就是scc-1 #include ...

  2. 利用jsonrpc技术包装uiautomator

    昨天一天在网上搜索解决上一篇文章中的exception: monkeyrunner内置uiautomator出错的原因 尽管没找到解决办法.可是让我无意中发现了一个好工具,比sl4a更好用的工具.直接 ...

  3. 蓝桥杯 第三届C/C++预赛真题(5) 转方阵(C基本功)

    对一个方阵转置,就是把原来的行号变列号,原来的列号变行号 例如,如下的方阵: 1 2 3 4 5 6 7 8 9 10 11 1213 14 15 16 转置后变为: 1 5 9 13 2 6 10 ...

  4. mui 子页面切换父页面底部导航

    在父页面中新增方法: function switchTab(tab){ plus.webview.hide(activeTab); activeTab= tab; plus.webview.show( ...

  5. CodeFirst中DbContext动态添加DbSet

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  6. numpy 和 pandas 中常用的一些函数及其参数

    numpy中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中. numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样本值.  ...

  7. iOS-常用宏定义

    下面我为大家提供一些常用的宏定义! 将这些宏定义 加入到.pch使用 再也不用 用一次写一次这么长的程序了 //-------------------获取设备大小------------------- ...

  8. manacher算法处理最长的回文子串(一)

    引言 相信大家都玩过折叠纸张,如果把回文串相当于折叠一个A4纸,比如ABCDDCBA就是沿着中轴线(D与D之间)对折重合,那么这个就是一个回文串.或者是ABCDEDCBA的中轴线就是E,那么沿着中轴线 ...

  9. Linux下自动调整时间和时区与Internet时间同步

    (原文链接) 调整linux系统时间和时区与Internet时间同步一.修改时区:# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime修改为中国的 ...

  10. jquery 轮播图实例

    实现效果:1.图片每2秒钟切换1次. 2.当鼠标停留在整个页面上时,图片不进行轮播. 3.当点击右下角的小球时,出现该选项的对应图片,而且切换页选项的背景颜色发生相应的变化. 4.当图片发生轮播切换时 ...