正则表达式与re模块
正则表达式与re模块
主要内容:
- 正则表达式
- Python的re模块
正则表达式
正则表达式(Regular expression)是一种利用事先规定好的特殊字符,及用这些特殊字符组合,组成一种具有某种规则的式子,来表达对字符串文本的过滤逻辑。正则表达式功能非常强大,所以许多语言都支持正则表达式,来增强对字符串的匹配替换等功能。因此正则表达式只是一种技术,它并不独属于任何一门语言,在Python中,需要利用re内置模块来书写正则表达式匹配字符串。
正则表达式的规则比较复杂,主要的常用的匹配规则可以分为以下几类。
1. 基础的字符:
普通的字符: 主要就是对应ASCII码表的那些基础字符, 如a-z, A-Z,0-9等等。
. : 点号再正则中,代表可以匹配任意除了换行符的字符
\: 反斜杠在正则中代表转义字符,例如\t 代表制表符, \n 代表换行符等
[...]: 字符集,字符集里面可以放入任何数量字符,这些字符之间是或的关系,整个字符集表示匹配里面的任一字符。字符集里可以用-连接ascii
码的和大的字符,表示匹配这个区间范围内的字符。
2. 预定义的字符:
\d: 同[0-9], 表示匹配数字
\D: 同[^\d], 表示匹配非数字
\w: 匹配字母数字下划线
\W: 匹配非字母数字下划线的所有字符
\s: 匹配空格
\S: 匹配非空格字符
3. 数量词:
* : *号在正则中表示可以匹配前面字符0-任意多次
? : ?号在正则中表示可以匹配前面字符0-1次
+:+号在正则中表示可以匹配前面字符1-任意多次
{m,n}: 表示匹配前面字符m-n次,其中m省略表示匹配0-n次,n省略表示匹配m-任意次
{m}: 表示匹配前面字符m次
注意: 在数量词中,比较特殊的是它们都并不能单独使用,只能与前面的字符配合使用(原因就是属于数量词),并且搭配使用数量词的时候,正则默认的匹配规则时贪婪模式,即会尽量的往多的匹
配,这时可以在数量次后面加?号来取消贪婪模式,变成非贪婪模式,如??, *?等等。
4. 边界匹配:
^: 上尖号在正则中表示匹配字符串的开头位置, 在字符集中表示取反
$:匹配字符串的结尾
\b: 匹配单词之间的边界。
注意: 这些边界匹配的时候是不会消耗字符的。
5. 逻辑分组
(...) 使用括号可以把一个表达式当做一个整体,后面可以跟数量词,并且这个分组在Python中有特殊意义
| 匹配左右两边的表达式,只要左边表达式匹配了,右边就不会去检测了
(?P<name> ...) 在原先分组的基础上,给分组取个别名,在Python中可以直接以这个名字来获取分组内容
一图胜千言,下面的图片就包含了基本所有正则表达式规则。

Python的re模块
Python中re模块相当于一个正则表达式的接口,使用这个接口,我们就能利用正则来处理Python中最基础的字符串了。
re模块最重要的三个方法:
re.findall(pattern, string, flags=0) pattern: 正则表达式 string:要匹配的字符串 flag: 正则表达式修饰符, 返回匹配的所有子串的列表,有分组则返回分组后的列表.
import re s = 'abc123abc' res = re.findall(r'abc', s) print(res)
['abc', 'abc']
re.search(pattern, string, flags=0) 扫描整个字符串,找到第一个匹配后返回一个match对象,最后需要利用group()方法获得匹配内容。
import re s = 'abc123abc' res = re.search(r'123', s) print(res) print(res.group())
<_sre.SRE_Match object; span=(3, 6), match='123'> 123
re.match(pattern, string, flags=0) 从字符串的起始位置开始匹配,如果字符串不符合正则表达式,则匹配失败,函数返回None, 否则返回一个匹配对象match.
import re s = 'abc123abc' res = re.match(r'123', s) res1 = re.match(r'abc', s) print(res) print(res1.group())
None abc
re模块的次要方法:
re.split(pattern, string, maxsplit=0, flags=0) pattern: 正则表达式 string: 匹配字符串 maxsplit: 最大分割次数 默认不限制次数 flags: 正则表达式修饰符, 返回按匹配字符串分割后的字符串列表
import re s = 'abc123abc' res = re.split(r'\d', s, 1) print(res) res = re.split(r'\d', s, 2) print(res) res = re.split(r'\d', s, 3) print(res)
['abc', '23abc'] ['abc', '', '3abc'] ['abc', '', '', 'abc']
从上面的例子可以看出来re模块的分割方法是分别拿匹配字符串去分割字符,每一次取回结果后,再拿新的匹配字符串来分割列表中的每一个字符串,这样就会出现上面所示的空字符串。
re.sub(pattern, repl, string, count=0, flags=0) pattern: 正则表达式 repl: 要替换的字符串或函数, string: 要匹配的字符串, count: 替换的次数, flags: 正则表达式修饰符, 返回替换后的新字符串
re.subn(pattern, repl, string, count=0, flags=0): 参数同sub, 但是返回的是一个元组(替换后的字符串, 替换次数)
上面两个函数基本使用方法一致。
import re
s = 'abc123abc'
res = re.sub('abc', 'bbb', s)
res1 = re.subn(r'abc', 'bbb', s)
print(res)
print(res1)
bbb123bbb
('bbb123bbb', 2)
re.compile(pattern, flags=0) pattern: 正则表达式, 将正则表达式编译成一个正则表达式对象Pattern, 当正则表达式很长且要反复使用时用它。
import re s = 'abc123abc' pattern = re.compile(r'abc') print(pattern.search(s).group())
abc
re模块分组的特殊用法
re模块分组后的匹配结果,可以通过group()方法获取,group方法默认传入0,代表整个匹配串,传入1,2...代表后面的分组序号,通过访问group(1)...等可以访问分组的内容。但是findall方法有些特殊,因为它返回列表,所以会优先返回分组的内容,这时候就需要在分组的前面加上?: 这个特殊语法来取消分组的特殊意义,只有当做一个整体的作用。
import re
s = 'abc123abc'
res = re.search(r'(abc)\d+(abc)', s)
res1 = re.search(r'(?P<name>abc)\d+(?P<age>abc)', s)
print(res.group())
print(res.groups())
print(res.group(1), res.group(2))
print(res1.group('name'), res1.group('age'))
abc123abc
('abc', 'abc')
abc abc
abc abc

浙公网安备 33010602011771号