Python正则学习

概览

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

re.match案例

re.match返回的是一个实例对象,调用它的方法找到结果。

假设我们需要匹配开头为”Ch_”的字符

1
2
3
4
5
6
7
8
9
import re

# 匹配成功返回一个实例对象
print re.match('Ch_', 'Ch_dog_v001')
>>> <_sre.SRE_Match object at 0x0000000003ACA510>

# 如果匹配失败,是没有返回值的
print re.match('Ch_', 'aCh_dog_v001')
>>> None

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

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

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

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

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

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

re.search案例

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

模糊匹配

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

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

    1
    2
    3
    4
    5
    6
    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 匹配除空格外的字符
以此类推…

1
2
3
4
res = re.search('a\dt', 'a6t')
print res.group(), res.start(), res.end()

>>> a6t 0 3
  • 匹配次数

? 表示匹配0-1次
+ 表示匹配1-无数次
* 表示匹配0-无数次

课堂小案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 字符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]: 匹配除去括号内字符以外的字符。
\: 转义符,给一些特殊符号去除符号作用。

课堂小案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 匹配开头,这和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
    (?#...): 注释

课堂小案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 比如只返回匹配.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/