Python的re模块


* re.compile 生成一个匹配器实例,用来匹配
* re.match 从字符最前端开始匹配
* re.search 从字符中搜索出第一个匹配结果
* re.findall 从字符中找出所有匹配结果
* re.sub 查询替换字符,返回替换结果
* re.subn 查询替换字符,返回替换结果和替换次数
* re.split 根据规则切分字符串

re.match案例

re.match返回的是一个实例对象,调用它的方法找到结果。
假设我们需要匹配开头为"Ch_"的字符

import re
# 匹配成功返回一个实例对象
print re.match('Ch_', 'Ch_dog_v001')
>>> <_sre.SRE_Match object at 0x0000000003ACA510>
# 如果匹配失败,是没有返回值的
print re.match('Ch_', 'aCh_dog_v001')
>>> None

group方法:用于获得一个或多个分组匹配的字符串

res = re.match('Ch_', 'Ch_dog_v001')
print res.group()
>>> Ch_

pos方法:找到匹配字符的index位置(好像这个方法永远都是返回0吧?)

res = re.match('Ch_', 'Ch_dog_v001')
print res.pos
>>> 0

注意re.match是从字符串前端开始匹配,如下情况需要匹配的字符在字符串中间,就会返回空值。

res = re.match('Ch_', 'HCH_Ch_dog_v001')
print res
>>> None

re.search案例

search方法则是从字符串中搜索出第一个匹配的结果

res = re.match('Ch_', 'HAH_Ch_dog_v001')
# 这里返回了实例,说明匹配成功
print res
>>> <_sre.SRE_Match object at 0x00000000031AA510>
print res.group()
>>> Ch_
# 匹配字符的起始index位置
print res.start()
>>> 4
# 匹配字符的结束index位置
print res.end()
>>> 7

模糊匹配

上面讲的是精确搜索,下面开始讲解模糊搜索。

使用中括号

使用[]可以找到括号里的任意一个字母匹配。

res = re.search('d[aoes]g', 'dog dag deg dsg')
print res
>>> <_sre.SRE_Match object at 0x0000000002FDA510>
print res.group()
>>> dog

或者[a-zA-Z0-9]这样匹配所有的小写和大写字母与数字。

使用转义字符模糊搜索

\d 匹配数字(0-9)
\w 匹配字母,数字和下划线 (a-z A-Z 0-9 _)
\s 匹配空格
\n 匹配换行的地方
. 匹配任何一个字符
转移字符大写,则是相反的效果,意思是匹配除去本义匹配的字符。
\D 匹配除数字外的字符
\S 匹配除空格外的字符
以此类推...

res = re.search('a\dt', 'a6t')
print res.group(), res.start(), res.end()
>>> a6t 0 3

匹配次数

? 表示匹配0-1次
+ 表示匹配1-无数次
* 表示匹配0-无数次
课堂小案例:

# 字符a和t之间有一个数字匹配成功
res = re.search('a\d?t', 'a6t')
print res.group(), res.start(), res.end()
# 字符a和t之间有多个数字匹配失败
res = re.search('a\d?t', 'a66666t')
print res
# 字符a和t之间没有数字匹配成功
res = re.search('a\d?t', 'at')
print res.group(), res.start(), res.end()
# 匹配条件:1开头,第二个数字是3,5,或者7,后面9位都是数字
res = re.search('1[357]\d{9}', '13910733521-45648356489')
print res.group(), res.start(), res.end()
>>> 13910733521 0 11
# 匹配3个以上的 a
res = re.search('a{3,}', 'abbaabbbaaabbbb')
print res.group(), res.start(), res.end()
>>> aaa 8 11
# 贪婪模式,匹配大于等于3个到小于等于9个 a,默认是往最大数量的找
'''
这里因为用的search, 所以如果匹配对象为'baaabaaaaaaaaab'
则会返回3个a,search是返回第一个符合匹配条件的对象。
'''
res = re.search('a{3,9}', 'aabaaaaaaaaaaaaaaab')
print res.group(), res.start(), res.end()
>>> aaaaaaaaa 3 12
# 非贪婪模式,加上?, 返回上面情况的最小数量
res = re.search('a{3,9}?', 'aabaaaaaaaaaaaaaaab')
print res.group(), res.start(), res.end()
>>> aaa 3 6

?号通常用于大区间匹配限制。
+?: 在匹配1到无数次时,取最小数量。
*?: 在匹配0到无数次时,取最小数量。
{m,n}: 在匹配m到n次时,取最小数量。

特殊符号

^: 表示匹配字符串开头。
$: 表示匹配字符串结尾。
|: 表示或,把正则表达式分为两段判断匹配。
(): 表示编组,括号里面的表达式作为一个整体逻辑。
[^ABC]: 匹配除去括号内字符以外的字符。
\: 转义符,给一些特殊符号去除符号作用。
课堂小案例:

# 匹配开头,这和match方法一样了。
res = re.search('^zhangly', 'zhanglyoooohhhh')
print res.group(), res.start(), res.end()
>>> zhangly 0 7
# 符号.表示匹配任何一个字符,这里用\去除它的作用
res = re.search('HS-\d{3}\.avi', 'this is lalala HS-009.avi lalala')
print res.group(), res.start(), res.end()
>>> HS-009.avi 15 25
# 如果需要匹配多个, 使用findall(), 返回一个列表
res = re.findall('HS-\d{3}\.avi', 'HS-988.avi lalala HS-009.avi lalala')
print res
>>> ['HS-988.avi', 'HS-009.avi']
# 符号()编组返回结果
res = re.search('(?P<zimu>[a-zA-Z]+)(?P<shuzi>\d+)', 'sgasgasg55648')
print res.groups()
>>> ('sgasgasg', '55648')
print res.groupdict()
>>> {'zimu': 'sgasgasg', 'shuzi': '55648'}
# 使用符号 | 返回多个匹配条件
res = re.findall('((aaa|bbb)\.txt)', 'gasgaaa.txtgasgwghbbb.txt')
print res
>>> [('aaa.txt', 'aaa'), ('bbb.txt', 'bbb')]
'''
列表中元组的第一个元素,是满足整个匹配条件的字符。
第二个元素是里层括号'(aaa|bbb)'满足条件的字符。
'''

逻辑判断

(?=abc): 判断字符后面包含abc
(?!abv): 判断字符后面不包含abc
(?<abc): 判断字符前面包含abc
(?<!abc): 判断字符前面不包含abc
(?#...): 注释
课堂小案例:

# 比如只返回匹配.jpg前面的字符
res = re.search('\w+(?=.jpg)', 'image001.jpg')
print res.group()
>>> image001
# 判断条件:字符是数字,并且字符后面不是.jpg
res = re.search('\d+(?!.jpg)', 'image001.jpg')
print res.group()
>>> 00
# 判断条件:字符是数字,并且字符前面是num
res = re.search('(?<=num)\d+', '123456num7890')
print res.group()
>>> 7890

课程推荐的一个检查正则表达式网站:
https://regex101.com/
这里的博客介绍也很详细,可以当作参考:
http://funhacks.net/2016/12/27/regular_expression/

(完)


From zero to hero