11.|11. 正则表达式

基于网络课程《Python全栈开发专题》 记录笔记,请支持正版课程。
  1. match:检测字符串是否匹配正则表达式
  2. search:在一个长的字符串中搜索匹配正则表达式的子字符串
  3. findall:查找字符串
  4. sub和subn:搜索和替换
  5. split: 通过正则表达式指定分隔符,通过这个分隔符将字符串拆分
文档 re模块官方文档: https://docs.python.org/3.6/library/re.html
match()
import re m = re.match('hello', 'hello') print(m)# <_sre.SRE_Match object; span=(0, 5), match='hello'> print(m.group())# hello # print(m.__class__) print(type(m))# print(m.__class__.__name__)# SRE_Match''' 如果匹配不到,m是 None ''' m1 = re.match('abc', '1111') if m1 is None: print('是的,没有匹配到')

search() search()只返回第一个匹配成功的结果。
from re import search, matchm1 = match('Python', 'Leif is short, you need Python') m2 = search('Python', 'Leif is short, you need Python') m3 = search('Python', 'Leif is short, you need Python. Python again.')if m1 is not None: print('m1: ', m1.group()) if m2 is not None: print('m2: ', m2.group()) if m2 is not None: print('m2: ', m2) if m3 is not None: print('m2: ', m3)# 只返回第一个匹配成功的结果

匹配多个字符"|"(或)
from re import match, search s = 'Python|Ruby|Java|C\+\+' m = match(s, 'hahaha ') print(m) m = search(s, 'I love Python.') print(m) m = search(s, 'I love Java.') print(m)

匹配单个字符"."(一个字符,转义)
from re import match, searchs = 'bin.' m = match(s, 'binxa') if m is not None: print(m.group())# binxm = search(s, '') print(m)s1 = '3.14' s2 = '3\.14'# 3.14m = match(s1, '3.14') print(m) m = match(s1, '3x14') print(m) m = match(s2, '3.14') print(m) m = match(s2, '3x14') print(m)# None

使用字符集"[]"(集合)
import re m = re.match('[aAbB]', 'a') print(m)print(1, re.match('a|b|cC|d', 'a')) print(2, re.match('a|b|cC|d', 'cC'))print(3, re.match('[abcd]', 'ab')) print(4, re.match('ab|cd', 'ab'))print(5, re.match('[ab][cd][ef][gh]', 'aceh')) print(6, re.match('[ab][cd][ef][gh]', 'aceX')) # None

重复、可选和特殊字符
  • *:0到n
  • +:1到n
  • ?:可选
''' 匹配'a' 'b' 'c'三个字母按顺序从左到右排列,而且这3个字母都必须至少有1个 abcaabcabbbcccbca(不匹配) ''' import re s = 'a+b+c' strList = ['abc','aabc','bbabc','aabbbcccxyz'] for value in strList: m = re.match(s, value) if m is not None: print(m.group()) else: print('{}不匹配'.format(value))

''' 匹配任意3个数字-任意3个小写字母 123-abc543-xyz1-xyz(不匹配)xyz-123(不匹配)\d: 代表数字 \w: 代表字符(中文也行) [a-z]{3}: 三个小写字母 ''' import res = r'\d{3}-[a-z]{3}' strList = ['123-abc','456-xyz','1234-xyz','1-xyzabc','657-xyz^%abc']for value in strList: m = re.match(s, value) if m is not None: print(m.group()) else: print('{}不匹配'.format(value))

''' 匹配以a到z的26个字母中的任意一个作为前缀(也可以没有这个前缀),后面至少有1个数字 ''' import res = r'[a-z]?[0-9]+' strList = ['1234','a123','ab456','b234abc']for value in strList: m = re.match(s, value) if m is not None: print(m.group()) else: print('{}不匹配'.format(value))

''' 匹配email ''' import res = r'[\w-]+@[\w\.]+\.com' # \w 中,不包含自fun strList = ['abc@126.com','test@mail.geeori.com','test-abc@geekori1.com','abc@geekori.com.cn']for value in strList: m = re.match(s, value) if m is not None: print(m.group()) else: print('{}不匹配'.format(value))

分组
  1. 只有圆括号括起来的部分才算一组,如果正则表达式中既有被圆括号括起来的部分,
    也有未被圆括号括起来的部分,那么只将圆括号括起来的部分算一组
  2. group方法,如果不指定参数,会返回匹配的整个字符串,如果加参数,会返回指定
    分组的字符串,组索引从1开始
  3. groups方法,以元组形式返回匹配的所有分组
import re m = re.match(r'(\d{3})-\d{4}-[a-z]{2}', '123-4567-xy') print(m.groups())# ('123',) print(m.group(1))# 123 print(m.group())# 123-4567-xy

字符串的首尾和单词边界
  • "^":匹配字符串的开始
  • "$":匹配字符串的结束
  • "\b":匹配单词边界
import re s = r'^\w+$' strList = ['aklskjdfklajsdklfj=', 'a; lskdjf', 'alsdkjflkasdjf'] for value in strList: m = re.match(s, value) if m is not None: print(m.group()) else: print('{}没有匹配到'.format(value))print('=========================================')s = r'\bthe\b' strList = ['you are the man', 'The USA', 'theme'] for value in strList: m = re.search(s, value)# 注意此处是search if m is not None: print(m.group()) else: print('{}没有匹配到'.format(value))

findall 和 finditer
  • findall:通过列表返回所有满足条件的字符串,DOM
  • finditer:将搜索结果通过一个迭代器返回,SAX
import res = '12-a-abc54-A-xyz---78-A-ytr' result = re.findall(r'\d\d-[aA]-[a-z]{3}', s) print(result)# ['12-a-abc', '54-a-xyz', '78-A-ytr']# 如果正则表达式里面有分组,则返回的是个二维列表 result = re.findall(r'(\d\d-[aA])-([a-z]{3})', s) print(result)# [('12-a', 'abc'), ('54-a', 'xyz'), ('78-A', 'ytr')]# re.I 忽略大小写: 这里的正则表达式没有A,但一样可以匹配到 result = re.findall(r'\d\d-a-[a-z]{3}', s, re.I) print(result)# ['12-a-abc', '54-A-xyz', '78-A-ytr']it = re.finditer(r'(\d\d)-a-([a-z]{3})', s, re.I) for result in it: print(result.group(), end = ' <') groups = result.groups() for i in groups: print(i, end = ' ') print('>')

使用sub和subn,搜索和替换
''' sub(正则表达式,要替换的字符串,原字符串) subn多返回一个替换个数 ''' import re result = re.sub('Bill', 'Mike', 'Bill is my son.') print(result)# Mike is my son.# subn: 除了替换结果,也会返回替换个数 result, counter = re.subn('Bill', 'Mike', 'Bill is my son, I like Bill') # print(result) print(result)# Mike is my son, I like Mike print('替换了{}个字符'.format(counter))# 替换了2个字符''' 中间的参数也可以是正则表达式 ''' s = '([0-9])([a-z]+)' result = re.sub(s, r'\1:\2', '01-1abc,02-2xyz,03-9hfg') print(result)# 01-1:abc,02-2:xyz,03-9:hfg# 也可以放在函数里面 def fun(): return r'\1:\2' result = re.sub(s, fun(), '01-1abc,02-2xyz,03-9hfg') print(result)# 01-1:abc,02-2:xyz,03-9:hfg

使用split()函数分割字符串
from re import splitresult = split('; ', 'Bill; Mike; John') print(list(result))# ['Bill', ' Mike', ' John']# 至少有1个逗号(,)或分号(; )或点(\.)或空白符(\s) result = split(r'[,; \.\s]+','a,b,,,d.x,; ok') print(result)# ['a', 'b', 'd', 'x', 'ok']# 第三个参数,只要前多少个值 # 返回的是列表,列表中最后一个元素是剩下的字符串 result = split(r'[,; \.\s]+', 'a,b,,,d.x,; ok', maxsplit=2) print(result)# ['a', 'b', 'd.x,; ok']

练习1 【11.|11. 正则表达式】编写一个正则表达式,匹配这几个单词:bat、Bit、But、hAt、hit、hut。
''' 1.编写一个正则表达式,匹配这几个单词:、、、、、。 ''' import restrList = ['bat', 'Bit', 'But', 'hAt', 'hit', 'hut'] # s = '^[bh][aiu]t$' s = r'[a-z]{3}' for value in strList: # 加上 re.I 参数,忽略大小写 m = re.match(s, value, re.I) if m is not None: print(m.group()) else: print('{}无法匹配'.format(value))

练习2
''' 2.编写一个正则表达式,匹配信用卡号。格式如下: xxxx xxxx xxxx xxxx,其中x表示0到9的数字。每一组是4个数字,组与组之间需要有至少一个空格。 1234 4321 5432 1234 ''' import res = r'^(\d{4}\s){3}\d{4}$' #s = '^\d{4}\s+\d{4}\s+\d{4}\s+\d{4}$'def checkRegex(value): m = re.match(s, value) if m is not None: print('正确的信用卡号:{}'.format(m.group())) else: print('{} 格式错误!'.format(value))# num = '1111 2222 3333 4444' # m = re.match(s, num) # print(m.groups())# ('3333 ',)!!!!!!!!!!!!!!while True: num = input("输入一个信用卡号:") if num == 'exit()': break checkRegex(num)

练习3
''' 3. 编写一个匹配日期的正则表达式,日期格式:YYYY-MM?-DD?。 其中YYYY表示4位的年,MM?表示1位或2位的月,DD?表示1位或2位的日。 而且4位的年必须在2000年以后,包括2000年。 例如,2001-4-5、2004-05-1都符合要求。 '''# 这个正则表达式不能排除14月,38号之类的错误。简单意思一下 s = r'^2\d{3}-[01]?\d-[1-3]?\d$' # s = '2\d{3}-\d{1,2}-\d{1,2}'from re import matchdef isMatch(date): m = match(s, date) if m is not None: print('{} is a date.'.format(m.group())) else: print('Not matched: {}'.format(date))isMatch('1999-12-31') isMatch('2011-1-41') isMatch('2050-14-5') isMatch('2050-12-31') isMatch('2050-12-39')

    推荐阅读