python中的正则表达式

re模块:match、search、findall、finditer、sub、compile

正则作用:1.查找内容,2.替换内容(内容为字符串,即文本)

match和search方法,返回的值是类

  • match和search的区别是, match能够匹配的是从头开始的内容,而search匹配的可以是不从头开始

必须能够将需求的字符串获取出来, 必须会写模式

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import re

# 当作爬虫获取的html或者是json文本
line = "huang123"

# 第二步, 人工 url
# 第三步, requests的入参就是url. requests的返回值html,json
# 第四步, 通过html, json 来获取具体需要存储的数据
# 第五步, 把具体需要存储的数据进行存储

# 需求是匹配huang
# pattern = 'huang'
# 需要两个参数, 模式, 文本内容
# match_res = re.match(pattern, line)
# print(match_res)
# 输出的结果:<re.Match object; span=(0, 5), match='huang'>

# 需求是匹配uang
# 匹配不是从头开始,所以使用search
# pattern = 'uang'
# match_res = re.search(pattern, line)
# print(match_res)

# 1.以h开头
# ^的作用是以它后面的字符作为开头
pattern = '^hua'
match_res = re.search(pattern, line)
print(match_res)

# 2.以h开头后面跟着一个字符
# `.`能够表示除了换行符的所有的字符
# 如果需要`.`匹配换行符,可以添加一个flag叫做re.S
line = 'h\n'
pattern = '^h.'
match_res = re.search(pattern, line, re.S)
print(match_res)

# 3.以h开头后面跟着任意数量的数字
# \d能够匹配数字
# *是能够将前面的字符重复0-n次 n>=0
# 贪婪,匹配尽量多的内容
# 非贪婪,匹配尽量少的内容
# ?如果跟在多次匹配的符号后面,他代表的就是非贪婪
line = "h122222eeee123"
pattern = '^h\d*?'
match_res = re.search(pattern, line, re.S)
print(match_res)

# 4.以3结尾
# $是以前面的字符作为结尾
pattern = '.*3$'
match_res = re.search(pattern, line)
print(match_res)

# 5.以h开头,以3结尾.中间只有一个字符
line = 'hkd3'
pattern = '^h.3$'
match_res = re.search(pattern, line)
print(match_res)

# 6.以h开头以3结尾中间可以存在任意数量的字符
pattern = '^h.*3$'
match_res = re.search(pattern, line)
print(match_res)
  • 正则中()的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import re

line = 'ahuuhhaaahang123'
# 1. 想要获取huuh
# 2. 使用非贪婪限定符

# pattern = 'huuh'
# res = re.search(pattern, line)
# print(res)

# 获取第一个h和第二个h他们之间的字符
# pattern = 'h.*?h' huuh
# pattern = 'h.*h.*?h' huuhhaaah
# pattern = 'h.*?h.*?h' huuhh
pattern = 'h(.*?h(.*))(h.*)h'
# 'h.*?h.*h.*h'
res = re.search(pattern, line)
# 如果需要将匹配到的内容获取出来, 就需要使用 res.group()
print(res.group(1))
print('2', res.group(2))
print('3', res.group(3))
#()里的数字代表着第几个括号,即先是第一个括号,第二个是第一个括号里面的括号,括号里的括号数完接着数外面的是第三个
  • 正则中{},+,?的使用
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
import re

line = 'ahuuhhaaahhhhang123'

# 需要获取h和h之间,需要包含特定数量字符的子串
# 使用 + h和h之间至少要有一个字符

# 获取h和h之间的字符是10个
# 花括号是如果只写一个数字{n}, 就是前面的字符重复n次
# 如果花括号内写的是两个数字{m, n}, 就是前面的字符重复m-n次
# 如果花括号内写的是一个数字{m, }, 代表的就是前面的字符重复m-无穷次
# * 与 {0,}
# pattern = 'h.{0,}h'
# res = re.search(pattern, line)
# print(res)

# 加好是指 前面的字符出现1到无穷次
# + 相当于 {1,}
line = 'ahuuhhaaahhhhang123'
# pattern = 'h.+?h.+?h'
# res = re.search(pattern, line)
# print(res)

# ? 代表着禁止贪婪, 如果前面是表示数量的限定词, 表示非贪婪
# ? 前面的字符出现0-1次, 如果他的前面是表示字符的词,那么就是0-1次
# ? 相当于 {0,1}

pattern = 'h?h'
res = re.search(pattern, line)
print(res)
  • 正则中|或者,[]的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import re

line = 'abc4'

# 匹配sss127 或者 aaa

# pattern = '(sss127)|(aaa)'
#
# res = re.search(pattern, line)
# print(res)

# 中括号, 当前的字符位置可以是哪些字符

# pattern = "[abcd]*\d+"
# res = re.search(pattern, line)
# print(res)

# 需要匹配所有的字母
line = 'abc4'
pattern = "[0-9]\d+"
res = re.search(pattern, line)
print(res)
  • \s匹配任何空白符,包括空格,制表符,换页符等等.等价于[\f\n\r\t\v]

  • \S匹配任何非空白符,等价于\f\n\r\t\v

  • \w等价于[A-Za-z0-9]

  • \W于\w相反

  • \d匹配所有数字,等价于[0-9]

findall的用法,找到匹配的所有的字符串,返回的是字符串列表

1
2
3
4
5
6
7
8
9
10
11
12
import re

line = 'aaaabbbbccccaaaa'

# 我们想要找到所有的aaaa
pattern = '.{4}'

res = re.search(pattern, line)
print(res)
res = re.findall(pattern, line)

print(res)

正则的练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import re

# text = "He was carefully disguised but captured quickly by police."
# pattern = '([a-zA-Z]*ly)[^a-zA-Z]'
# res = re.findall(pattern, text)
#
# print(res)

text = '''Ross McFluff: 834.345.1254 155 Elm Street Ronald Heathmore: 892.345.3428 436 Finley Avenue Frank Burger: 925.541.7625 662 South Dogwood Way Heather Albrecht: 548.326.4584 919 Park Place'''

pattern = '(.*): (\d{3}\.\d{3}\.\d{4}) (.*)'

res = re.findall(pattern, text)
# print(res)

result_dict = {}
for item in res:
name = item[0]
phone_num = item[1]
addr = item[2]
result_dict[name] = {'phone_num': phone_num, 'address': addr}

print(result_dict)

finditer的使用

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
36
37
38
39
40
import re
# 引入compile
def my_finditer(pattern, text):
# 1. 频繁的创建销毁对象会占用很多的资源
# 2. 在re.search中会生成一个匿名的对象, 执行search操作
# 3. 每一次执行re.search都会生成一个对象并且销毁一个对象
# 4. 循环的时候, 就可能会大量的创建并销毁compile对象, 时间复杂度O(n)
# 5. 循环的时候, 由于pattern和flag是不变的, 那么就说明对象可以不重新创建, 只用一个就可以
# 6. 在循环外创建对象, 循环内调用对象.search(text), 时间复杂度就是 O(1)
# search如何调用
# re.search(pattern, text)
# re.search就相当于
pat_obj = re.compile(pattern)
print('生成器开始工作')
# print(type(pat_obj))
# res = pat_obj.search(text)
# 定义一个开始的pos
pos = 0
#res_list = []
# 做出循环, 循环的找到需要的内容
while True:
print('生成器循环')
res = pat_obj.search(text, pos)
if res == None:
break
pos = res.end()
print('我返回给你一个内容:', res)
yield res
if __name__ == '__main__':
text = "He was carefully disguised but captured quickly by police."
pattern = '\w*ly'
# res = re.finditer(pattern, text)
# print(res)
# for item in res:
# print(item.group(0))
# 1. 生成器和列表有一点类似, 都可以通过 for.. in ..: 访问
res = my_finditer(pattern, text)
print(res)
for item in res:
print('我收到了:' , item)

sub的使用

1
2
3
4
5
6
7
8
9
10
import re
# sub 就是将匹配到的内容替换成 特定的字符串
# 匹配是需要pattern的, 替换成什么样的内容 replace_str, 需要做替换的文本 text

text = "He was carefully disguised but captured quickly by police."
pattern = '\w*ly'
# res = re.findall(pattern, text)

res = re.sub(pattern, 'dog', text)
print(res)