正则表达式(二)
re模块(regex)
python中没有正则表达式的函数,需要引入内置的re模块
-
re模块方法:
- match:从头开始匹配,只匹配一个结果
- 作用:接收用户传递过来的url进行匹配(web框架用到)
- search:整个字符串进行匹配,只匹配第一个获得的结果
- findall:匹配整个字符串,返回一个列表对象
- finditer:和findall非常类似,返回一个可迭代的对象,迭代的时候才会创建值
- split:字符串切割
- sub:替换
- 最常用match和findall来查找
- match:从头开始匹配,只匹配一个结果
-
分组的作用:
- 在匹配得到的结果中获取局部的值
-
re模块查找分类(match,search,findall):
- 普通匹配:
- 通过match和search匹配成功返回的对象中,group得到的匹配得到的完整结果
regex = 'H\w+' ret = re.match(regex, origin) print(ret.group()) # Hello print(ret.groups()) # () print(ret.groupdict()) # {}
- 分组匹配:
- 分组来获取局部的值
- match:从头开始匹配
origin = 'Hello tom, xxx tom, yyy tom haha 19' regex = '(H)(\w+)' ret = re.match(regex, origin) print(ret.group()) # Hello print(ret.groups()) # ('H', 'ello') print(ret.groupdict()) # {}
origin = 'Hello tom, xxx tom, yyy tom haha 19' regex = '(?P<n1>H)(\w+)' ret = re.match(regex, origin) print(ret.group()) # Hello print(ret.groups()) # ('H', 'ello') print(ret.groupdict()) # {'n1': 'H'}
search:知道了group方法之后,searh方法和match方法是一样的,match是从头开始匹配,search是全局匹配
-
findall:返回匹配成功的列表
- 不分组:
regex = 'app\w+' origin = 'i have an apple, i have a pen, apple pen' ret = re.findall(regex, origin) print(ret) # ['apple', 'apple']
- 分组:
- findall会把groups里面的所有东西放到列表里面(分组的作用:获取局部的东西)
- findall对?P<key>不起作用
- 如果分组嵌套分组,则先取外面的,再取里面的
egex = '(app\w+)' origin = 'i have an apple, i have a pen, apple pen' ret = re.findall(regex, origin) print(ret) # ['apple', 'apple'] regex = '(app)\w+' origin = 'i have an apple, i have a pen, apple pen' ret = re.findall(regex, origin) print(ret) # ['app', 'app'] regex = '(app)(\w+)' origin = 'i have an apple, i have a pen, apple pen' ret = re.findall(regex, origin) print(ret) # [('app', 'le'), ('app', 'le')] regex = '((a)(pp))(\w+)' origin = 'i have an apple, i have a pen, apple pen' ret = re.findall(regex, origin) print(ret) # [('app', 'a', 'pp', 'le'), ('app', 'a', 'pp', 'le')]
-
finditer:只有在迭代的时候才创建对象
- 迭代的对象跟match和search获得的对象一样
regex = '((a)(pp))(\w+)' origin = 'i have an apple, i have a pen, apple pen' ret1 = re.search(regex, origin) print('type of search', type(ret1)) # type of search <class '_sre.SRE_Match'> ret2 = re.finditer(regex,origin) for i in ret2: print('type of finditer', type(i)) # type of finditer <class '_sre.SRE_Match'>
- 普通匹配:
-
分组注意事项:
- 分组的是按照你真是写了多少个组来确定的,如果获得的值多于写的组个数,则去最后一个
regex = '(\w)(\w)(\w)(\w)' ret = re.findall(regex, 'tony') print(ret) # [('t', 'o', 'n', 'y')] regex = '(\w){4}' ret = re.findall(regex, 'tony') print(ret) # [y]
- 第一个写了4个组,每个组一个字符:(\w)(\w)(\w)(\w),所以得到的结果是4个组
- 第二个写的是1个组,需要匹配4个字符,因为真正写的只有一个组,所有得到的结果为1个组,理论上每个字符的组都是一样的,最后的会覆盖前面的,所以取得的是最后一个
ret = re.findall('\dyhh*', '1yhh2yhh3andyhh4yhh') print(ret) # ['1yhh', '2yhh', '4yhh'] ret = re.findall('(\dyhh)*', '1yhh2yhh3andyhh4yhh') print(ret) # ['2yhh', '', '', '', '', '', '', '', '4yhh', '']
- 匹配时尽量避免正则表达式为空值
-
split:分割
- 无分组分割:分割后不包含自己(分隔符)
- 分组分割:分割后会保留分割符内分组的内容
regex = '\d+' origin = 'ad12ad134a34da' ret = re.split(regex, origin) print(ret) # ['ad', 'ad', 'a', 'da'] regex = '(\d+)' origin = 'ad12ad134a34da' ret = re.split(regex, origin, 1) print(ret) # ['ad', '12', 'ad134a34da']
- 使用场景:计算器获取最里层的括号同时取出括号
origin = '7+((3+4)*5-(4-9)*5)*4' regex = '\(([^()]+)\)' # 获取最里层的括号,同时对括号里的数据归到组里,切割后保留括号内的内容 ret = re.split(regex, origin, maxsplit=1) print(ret) # ['7+(', '3+4', '*5-(4-9)*5)*4']
- 再根据切割后得到的结果是否是长度为3的列表,不断循环计算其值
while True: ret = re.split(regex, origin, maxsplit=1) if len(ret) == 3: 计算得到括号的值,然后重新组合origin字符串 elif: break同时带出结果
sub:替换 && subn:替换返回一个元组