了解接触正则表达式已经很长时间了,但是近期通过查阅资料、网站等才对于python正则有了一个系统学习,并写了这篇学习总结。关于写东西总结归纳这个过程,个人觉得有利于提升自身各能力,对知识也有一个更深入的认识,是一个很有意义的过程。希望22年可以静下心来不断学习知识,提升自己。
正则表达式(Regular Expression)简称RE,是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
先来看一张导图,熟悉大概的知识点:
下面将根据 xmind 图所示,介绍 re 模块中常用常量、方法以及常用字符:
一、re模块(re是内置模块,所以不需要再下载,使用时直接引入即可)
1、常量(re模块中有9个常量,一般常用的有5个)
(1)re.IGNORE或re.I 忽略大小写匹配
text = "今天是yuandan"
pattern = r'今天是YUANDAN'
pattern_obj_1 = re.compile(pattern)
pattern_obj_2 = re.compile(pattern, re.I)
print(pattern_obj_1.findall(text))
print('IGNORE:', pattern_obj_2.findall(text))
>>>['今天是']
>>> ['今天是yuandan']
(2)re.ASCII或re.I 只匹配ASCII码
# 未加re.A
text = 'a今b天c是d元3_4旦56 '
pattern = r'\w+'
pattern_obj_1 = re.compile(pattern)
pattern_obj_2 = re.compile(pattern, re.A)
print(pattern_obj_1.findall(text))
print('ASCII:', pattern_obj_2.findall(text))
>>>['a今b天c是d元3_4旦56']
>>>ASCII:['a', 'b', 'c', 'd', '3_4', '56']
(3)re.DOTALL abbreviation:re.S 匹配所以包括\n(换行符)
text = 'a今b天\nc是d元3_4\n旦5 6'
pattern = r'.+'
pattern_obj_1 = re.compile(pattern)
pattern_obj_2 = re.compile(pattern, re.S)
print(pattern_obj_1.findall(text))
print('DOTALL:', pattern_obj_2.findall(text))
>>>['a今b天c是d元3_4旦5 6']
>>>DOTALL:['a今b天\nc是d元3_4\n旦5 6']
(4)re.MULTLINE abbreviation:re.M 多行模式,当某字符串中有换行符\n,默认模式下是不支持换行符特性的,比如:行开头 和 行结尾,而多行模式下是支持匹配行开头的
text = '今天是\n元旦'
pattern = r'^元旦$'
pattern_obj_1 = re.compile(pattern)
pattern_obj_2 = re.compile(pattern, re.M)
print(pattern_obj_1.findall(text))
print('MULTLINE:', pattern_obj_2.findall(text))
>>>[]
>>>MULTLINE:['元旦']
(5)re.VERBOSS abbreviation:re.X 详细模式,可以在正则表达式中添加注释
text = '今天是元旦'
pattern = r'''
今天是 # 时间
元旦 # 节日
'''
pattern_obj_1 = re.compile(pattern)
pattern_obj_2 = re.compile(pattern, re.X)
print(pattern_obj_1.findall(text))
print('VERBOSS:', pattern_obj_2.findall(text))
>>>[]
>>>VERBOSS:['今天是元旦']
2、方法(9个常用方法)
(1)re.compile(pattern, flags=0) 编译正则对象
‘’’
在re的正则表达式模块里,可以通过模块的方式来访问正则表达式,但是如果重复多次地使用正则表达式,最好是使用compile函数把正则表达式编译成对象RegexObject,这样会大大地提高搜索的效率,因为基于非编译方式访问时,是使用模块里的一小块缓冲来进行的。
‘’’
建议先进行预编译,在进行匹配;
(2)搜索返回一个匹配结果(search、match、fullmatch)
re.search(pattern, string, flags=0) 查找任意位置匹配项
pattern:匹配规则
string:查找对象
flags:常量 例如:re.I
text = '今天是周日,明天是周一,'
pattern = r'是'
print(re.search(pattern, text, flags=0).group())
# 预编译
pattern_obj = re.compile(pattern)
print(pattern_obj.search(text).group())
# group()会在后面介绍到
>>>是
>>>是
re.match(pattern, string, flags=0) 从字符串开头开始匹配
text_1 = 'a今天是周日,明天是周一'
text_2 = '今天是周日,明天是周一'
pattern = r'今天是周日'
print(re.match(pattern, text_1, flags=0))
print(re.match(pattern, text_2, flags=0).group())
# 预编译
pattern_obj = re.compile(pattern)
print(pattern_obj.match(text_2).group())
>>>None
>>>今天是周日
>>>今天是周日
re.fullmatch(pattern, string, flags=0) 完全匹配字符串
pattern_1 = r'今天是周日'
pattern_2 = r'今天是周日,明天是周一'
print(re.fullmatch(pattern_1, text, flags=0))
print(re.fullmatch(pattern_2, text, flags=0).group())
>>>None
>>>今天是周日,明天是周一
(3)搜索返回多个匹配结果(findall,finditer)
re.findall(pattern, string, flags=0) 从字符串任意位置查找,返回一个列表
text = '今天是周日,明天是周一'
pattern = r'天'
print(re.findall(pattern, text, flags=0))
>>>['天', '天']
re.finditer(pattern, string, flags=0) 从字符串任意位置查找,返回一个迭代器
text = '今天是周日,明天是周一'
pattern = r'天'
print(re.finditer(pattern, text))
print(list(re.finditer(pattern, text)))
print(list(re.finditer(pattern, text))[0])
print(list(re.finditer(pattern, text))[0].group())
>>> <callable_iterator object at 0x02C535F0>
>>>[<_sre.SRE_Match object; span=(1, 2), match='天'>, <_sre.SRE_Match object; span=(7, 8), match='天'>]
>>>_sre.SRE_Match object; span=(1, 2), match='天'>
>>>天
(4)分割
re.split(pattern, string, maxsplit=0, flags=0) 分割字符串,与str.split( )作用一致
pattern:匹配规则
string:查找对象
maxsplit:最多进行分割次数,默认全部
flags:常量 例如:re.A
re.split()与str.split()区别
str.split函数功能简单,不支持正则分割,而re.split支持正则。
数据量越大re.split()运行速度越大于str.split(),数据量较小情况下建议使用str.split(),数据量上千次或越大使用re.split()
text = '今天是周日0明天是周一0马上要收假了'
pattern = '0'
print(re.split(pattern, text))
text_2 = '今天是周日0明天是周一0马上要收假了'
print(text_2.split('0'))
>>>['今天是周日', '明天是周一', '马上要收假了']
>>>['今天是周日', '明天是周一', '马上要收假了']
(5)替换
re.sub(pattern, repl, string, count=0, flags=0) repl替换掉string中被pattern匹配的字符
text = '今天是周日0明天是周一0马上要收假了'
pattern = '0'
print(re.sub(pattern, ',', text))
>>>今天是周日,明天是周一,马上要收假了
(6)清理缓存
re.purge() 清理正则表达式缓存
二、group
1、正则表达式中的三组括号把匹配结果分成三组
group() 同 group(0) 匹配正则表达式整体结果
group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号, 在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
2、没有匹配成功的,re.search()返回None。
3、正则表达式中没有括号,group(1) 报错:IndexError: no such group。
三、常用字符
1、一般字符
字符 | 用途 |
---|---|
. | 匹配任意一个字符(除了\n),在DOTALL模式中可以匹配到\n |
\ | 转义字符,如果字符串中有字符要匹配,可使用*或[] |
[ ] | 匹配[]中列举的字符,在[]中要使用] 、- 或 ^,可以在前面加\ 把] 、-放在第一个字符,^放在非第一个字符 |
2、常用元字符
字符 | 用途 |
---|---|
\d | 匹配数字,即0-9 |
\D | 匹配非数字,即[^0-9] |
\s | 匹配空白字符,即空格、tab键 |
\S | 匹配非空白字符 |
\w | 匹配数字、字母、下划线、汉字,即0-9、a-z、A-Z、_、汉字 |
\W | 匹配非数字、非字母、非下划线、非汉字 |
3、常用限定符
字符 | 用途 |
---|---|
* | 匹配前一个字符0或无限次,匹配不一致列表中显示”” |
+ | 匹配前一个字符1或无限次 |
? | 匹配前一个字符0或1次 |
{m} | 匹配前一个字符m次 |
{m,n} | 匹配前一个字符m到n次 |
4、限定字符
字符 | 用途 |
---|---|
^ | 匹配字符串开头,在多行模式中匹配每一行开头,[^]代表不在[]中的字符 |
$ | 匹配字符串的末尾,在多行模式中匹配每一行的末尾 |
\A | 匹配字符串的开头 |
\Z | 匹配字符串的末尾 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
四、贪婪与非贪婪
贪婪模式:python中默认贪婪模式,总是尝试匹配尽可能多的字符
非贪婪模式:总是尝试匹配尽可能少的字符
在python中默认采用的是贪婪模式,使用非贪婪模式的话,只需要在量词后面直接加上一个问号”?”
text = 'abbbskfk babdj '
pattern_1 = r'ab+'
pattern_2 = r'ab+?'
print(re.findall(pattern_1, text))
print(re.findall(pattern_2, text))
>>>['abbb', 'ab']
>>>['ab', 'ab']