IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python正则表达式必知必会的基础 -> 正文阅读

[Python知识库]python正则表达式必知必会的基础

正则表达式

本文主要讲的是正则表达式在python中的简单使用,只介绍关键的几个方法函数,就不赘述正则表达式的基础知识了。在我个人的工作学习生活场景中,正则表达式主要用在清洗数据、路由代码、判断用户输入字段是否合规等场景,很简单,拆开来说,无非就下面这些常见的使用场景,使用的函数也就那几个,其他现学现卖就好了。

  • 从头到尾只匹配一次,即匹配到第一次就返回结果,若匹配不到就返回None

    • 从头开始匹配:re.match(),例如检验用户输入的手机号是否合规、路由匹配
    • 不从头开始匹配:re.search(),多用在寻找目标字段,可通过其groups属性提取
  • 从头到尾找多次

    • re.findall(),返回匹配到的字符串列表,这个后面细说
  • 替换数据

    • re.sub(),很多时候要清洗文本中的换行符等字符,或者是替换日期格式等操作

从我的角度来说,re.search()是使用最多的,结合分组、命名等使用方式写个匹配规则,然后search一下,提取目标字段。然后就是标识符需要好好看看,很多时候感觉表达式对了,但是就是匹配不到,很可能是因为标识符没设置,在你掌握了re.search()flags后,已经能应付很多需求了,其他函数也自然就触类旁通,接下来开始正文。

re.match()和re.search()

SRE_Match object

为什么要把re.match()和re.search()放在一起说呢,因为它们两个返回的是同一种对象,官方描述是SRE_Match object,其打印结果如下所示。

text = '<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'

reg = r'<.*?>(?P<content>.*?)</.*?>'

res01 = re.match(pattern=reg, string=text, flags=re.S + re.M)
res02 = re.search(pattern=reg, string=text, flags=re.S + re.M)
print(res01)
print(res02)

print(type(res01))
print(type(res02))

# 打印结果
<_sre.SRE_Match object; span=(0, 34), match='<p>asdasdasaaa\nsdghaasdasdsdfs</p>'>
<_sre.SRE_Match object; span=(0, 34), match='<p>asdasdasaaa\nsdghaasdasdsdfs</p>'>
<class '_sre.SRE_Match'>
<class '_sre.SRE_Match'>

这个search_match_obj中有几个常用的属性和方法

res = re.search(pattern=reg, string=text, flags=re.S)
res.group()   # 只获取第一组的字符串
res.groups()  # 获取组元组
res.groupdict()  # 获取组的key:value对
res.span()		# 匹配的串的开始:结束位  (0, 34)

re.match()

re.match()尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

函数语法

re.match(pattern, string, flags=0)

函数参数说明:

参数描述
pattern匹配的正则表达式。
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

匹配成功re.match()返回一个匹配的对象,否则返回None。可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

使用场景:例如检验用户输入的手机号是否合规、路由匹配等。

使用示例:

text = 'aa<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'
reg = r'<.*?>(?P<content>.*?)</.*?>'
res = re.match(pattern=reg, string=text, flags=re.S + re.M)
print(res)   # 因为一开头就匹配不上,将返回None


# 如下情况则能匹配到
text = 'aa<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'
reg = r'<.*?>(?P<content>.*?)</.*?>'
res = re.match(pattern=reg, string=text, flags=re.S + re.M)
print(res)    # SRE_Match object
print(res.group())
print(res.groups())
print(res.groupdict())

打印结果如下:
<_sre.SRE_Match object; span=(0, 34), match='<p>asdasdasaaa\nsdghaasdasdsdfs</p>'>

<p>asdasdasaaa
sdghaasdasdsdfs</p>

('asdasdasaaa\nsdghaasdasdsdfs', 'p')

{'content': 'asdasdasaaa\nsdghaasdasdsdfs'}

(0, 34)

re.search()(重点)

re.search 扫描整个字符串并返回第一个成功的匹配。

函数语法:

re.search(pattern, string, flags=0)

函数参数说明:

参数描述
pattern匹配的正则表达式
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

匹配成功re.search()返回一个匹配的对象,否则返回None。可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

image-20210803211907846

使用场景:例如检验用户输入的手机号是否合规、路由匹配等。

使用示例:多用在寻找目标字段,提取、清洗数据。

import re

text = '<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'

# 一个分组,并命名为content,.*?是非贪婪模式下匹配任意字段
reg = r'<.*?>(?P<content>.*?)</.*?>'
res = re.search(pattern=reg, string=text, flags=re.S + re.M)
print(res)
print(res.group())
print(res.groups())
print(res.groupdict())

# 打印结果如下
<_sre.SRE_Match object; span=(0, 34), match='<p>asdasdasaaa\nsdghaasdasdsdfs</p>'>
<p>asdasdasaaa
sdghaasdasdsdfs</p>
('asdasdasaaa\nsdghaasdasdsdfs',)
{'content': 'asdasdasaaa\nsdghaasdasdsdfs'}

分组的意义,就是在匹配成功的字符串中,再提取()里面的字符串,re.search中通过groupdict()拿到分组对应的内容。

re.flags

前文中,关于flags的使用如下:

res = re.search(pattern=reg, string=text, flags=re.S + re.M)

re.S + re.M 代表同时使用两种模式,re.S主要是为了让.匹配到\n,而re.M则是为了避免因为有\n而导致的换行匹配不成功,下面将对各个标识符的模式简要介绍一下,需要了解具体说明的看客还请移步官网等教程。

  • re.I(re.IGNORECASE)

    • 忽略大小写匹配
  • re.A(re.ASCII)

    • \w, \W, \b, \B, \d, \D, \s\S 只匹配ASCII,而不是Unicode。在默认匹配模式下\w+匹配到了所有字符串,而在ASCII模式下,只匹配到了a、b、c(ASCII编码支持的字符)。
    • 只对字符串匹配模式有效,对字节匹配模式无效。
  • re.S(re.DOTALL)

    • DOT表示.,ALL表示所有,连起来就是.匹配所有,包括换行符\n
    • 默认模式下.是不能匹配行符\n
  • re.M(re.MULTILINE)

  • 多行模式,当某字符串中有换行符\n,默认模式下是不支持换行符特性的,比如:行开头 和 行结尾,而多行模式下是支持匹配行开头的。

    • 正则表达式中^表示匹配行的开头,默认模式下它只能匹配字符串的开头;而在多行模式下,它还可以匹配 换行符\n后面的字符。
  • 正则语法中^匹配行开头、\A匹配字符串开头,单行模式下它两效果一致,多行模式下\A不能识别\n

  • re.X( re.VERBOSE)

    • 详细模式,可以在正则表达式中加注解
    • 默认模式下并不能识别正则表达式中的注释,而详细模式是可以识别的。
  • re.L(re.LOCALE)

    • 由当前语言区域决定 \w, \W, \b, \B 和大小写敏感匹配,这个标记只能对byte样式有效。
    • 官方不推荐使用
  • re.U (re.UNICODE)

    • 匹配unicode编码支持的字符
    • Python 3 默认字符串已经是Unicode,不推荐使用
  • re.DEBUG

    • 显示编译时的debug信息,了解即可
  • re.T(re.TEMPLATE)

    • disable backtracking(禁用回溯),了解即可

小结

标志位总共有9个常量,其中:

  • 常用:IGNORECASE、ASCII、DOTALL、MULTILINE、VERBOSE
  • 几乎不用:LOCALE、UNICODE、TEMPLATE、DEBUG

re.sub()

该函数用于将匹配到字符串替换成目标字符。

语法:

re.sub(pattern, repl, string, count=0, flags=0)

参数:

  • pattern : 正则中的模式字符串。
  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

示例:

text = 'aa<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'
reg = r'<.*?>'
res = re.sub(pattern=reg, string=text, flags=re.S + re.M, repl=' ')
print(res)  

# 打印结果
aa asdasdasaaa
sdghaasdasdsdfs kkkkkkkkkkkkk

re.subn(pattern, repl, string, count=0, flags=0) 函数与 re.sub函数 功能一致,只不过返回一个元组 (字符串, 替换次数)。

re.split()

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string, maxsplit=0, flags=0)

参数:

参数描述
pattern匹配的正则表达式
string要匹配的字符串
maxsplit分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

示例

text = 'aa<p>asdasdasaaa\nsdghaasdasdsdfs</p>kkkkkkkkkkkkk'
reg = r'<.*?>'
res = re.split(pattern=reg, string=text, flags=re.S + re.M)
print(res)  # 因为一开头就匹配不上,将返回None

re.findall()

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

语法格式为:

re.findall(pattern, string, flags=0)

参数:

  • string : 待匹配的字符串。
  • pos : 可选参数,指定字符串的起始位置,默认为 0。
  • endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

使用场景:多用于找到所有目标字段。

实例

str = 'aabbabaabbaa'

# 一个"."就是匹配除 \n (换行符)以外的任意一个字符
print(re.findall(r'a.b',str)) # ['aab', 'aab']

# *前面的字符出现0次或以上
print(re.findall(r'a*b',str)) # ['aab', 'b', 'ab', 'aab', 'b']

# 贪婪,匹配从.*前面为开始到后面为结束的所有内容
print(re.findall(r'a.*b',str)) # ['aabbabaabb']

# 非贪婪,遇到开始和结束就进行截取,因此截取多次符合的结果,中间没有字符也会被截取
print(re.findall(r'a.*?b',str))  # ['aab', 'ab', 'aab']

# 非贪婪,与上面一样,只是与上面的相比多了一个括号,只保留括号的内容
print(re.findall(r'a(.*?)b',str))    # ['a', '', 'a']
 
str = '''aabbab
         aabbaa
         bb'''     # 后面多加了2个b

# 没有把最后一个换行的aab算进来
print(re.findall(r'a.*?b',str)) # ['aab', 'ab', 'aab']

# re.S不会对\n进行中断
print(re.findall(r'a.*?b',str,re.S)) 
# ['aab', 'ab', 'aab', 'aa\n         b']

re.finditer(pattern, string, flags=0用法与re.findall()差不多,但是前者返回的是迭代器,需要对其进行遍历,才能获取数据,后者则直接是个列表,为什么这么设计呢?这里我本人暂时也不清楚,貌似是因为使用finditer时,无需手动将整个正则用()括起来group()代表整个正则的匹配,这里的需求场景比较特殊,后面若深挖,我将继续分享。

re.fullmatch()

re.fullmatch()的返回值re.match()和re.search()一样都是一个SRE_Match object,fullmatch是完全匹配(从字符串开头到结尾),而match()只是从头匹配,但从理论上来说,能用fullmatch实现的,用match也都能实现。

即,fullmatch(pattern, string, flags=0) ,是match函数的完全匹配(从字符串开头到结尾)版本。

示例:

qq = '1234567890'
res01 = re.fullmatch(r'[1-9]\d{4,11}', qq)
res02 = re.match(r'^[1-9]\d{4,11}$', qq)

print(res01)
print(res02)
# <_sre.SRE_Match object; span=(0, 10), match='1234567890'>
# <_sre.SRE_Match object; span=(0, 10), match='1234567890'>

re.compile()

在Python中使用正则表达式时,re模块内部会干两件事情:

  • 编译正则表达式,如果正则表达式的字符串本身不合法,会报错;

  • 用编译后的正则表达式去匹配字符串。

那么如果一个正则表达式要重复使用几千次,出于效率的考虑,应该先把这个正则先预编译好,接下来重复使用时就不再需要编译这个步骤了,直接匹配,提高我们的效率。

re.compile(pattern, flags=0)接受pattern和flags两个参数,使用简单示例如下:

re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')  # 编译

A = re_telephone.match('010-12345').groups()  # 使用
print(A)  # 结果 ('010', '12345')
B = re_telephone.match('010-8086').groups()  # 使用
print(B)  # 结果 ('010', '8086')

小结

方法分类

查找一个匹配项

  • re.search()

  • re.match()

  • re.fullmatch()

查找多个匹配项

  • re.findall()

  • re.finditer()

替换

  • re.sub()
  • re.subn()

分割

  • re.split()

编译

  • re.compile()

注意细节

  1. 字节串 与 字符串

    模式和被搜索的字符串既可以是 Unicode 字符串 (str) ,也可以是8位字节串 (bytes)。 但是,Unicode 字符串与8位字节串不能混用。

  2. 反斜杠和r的使用

    正则表达式使用反斜杠/来表示特殊形式,或者把特殊字符转义成普通字符。反斜杠在普通的 Python 字符串里也有相同的作用,所以就产生了冲突。解决办法是对于正则表达式样式使用 Python 的原始字符串表示法;在带有 ‘r’ 前缀的字符串字面值中,反斜杠不必做任何特殊处理。

  3. 重复使用某个正则

    如果要重复使用某个正则表达式,可使用re.compile()优化。

正则表达式网站

  • 练习网站:https://regexone.com/

    由浅入深,旁边还有提示,刷完后正则表达式的掌握程度就立马上来了!

image-20210803152806742

  • 测试网站:https://regexr.com/

    把目标文本粘贴进去,然后在上方输入你的表达式,匹配到的都会高亮显示,且提示非常全,下面还会有匹配表达式的规则解析说明。

image-20210803151108189

参考资料

https://zhuanlan.zhihu.com/p/127807805

https://www.runoob.com/python/python-reg-expressions.html

https://regexr.com/

https://regexone.com/

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-08 13:35:08  更:2021-08-08 13:35:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 10:01:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码