「Python 正则」使用专题总结
Python实战社群
Java实战社群
长按识别下方二维码,按需求添加
扫码关注添加客服
进Python社群▲
扫码关注添加客服
进Java社群▲
作者丨zhenguo
来源丨Python与算法社区
今天开始Python进阶模块总结之正则专题,目录结构如下:
1 学习正则的价值
2 正则学习前的几个准备
Q1 字符 `r`是干啥的?
Q2 什么是一个原子操作?
Q3 怎么理解正则中的转义?
3 掌握最常用规则
情况1:最普通查找
情况2:使用通用字符
情况3:使用元字符
4 有个棘手的场景
5 学会提取子串的技能
6 使用捕获的注意事项
1 学习正则的价值
正则应用广泛。不仅在Python语言中使用,其他语言也都在用,并且不同语言间的正则语法极为相似。同时主流操作系统,尤其linux系统的命令窗口中,也会经常使用到正则。还有,Python的常用包如Pandas,也经常遇到正则。
不仅使用广泛,正则功能也很强大,还有书写简便,因此这项技能值得我们仔细研究和掌握。
2 正则学习前的几个准备
Q1 字符 r
是干啥的?
经常见过正则表达式前有一个字符 r
,它的作用是告诉解释器后面的一串是原生字符串,按照字面意思解释即可。如:
s1 = r'\n.*'
print(s1)
它告诉编译器s串第一个字符是\
,第二个字符是n
.打印的结果就是它本身:
\n.*
而如果不带前缀字符r
,即:
s2 = '\n.*'
print(s2)
解释器认为前两个字符\n
为转义字符,一个新行的意思,打印结果为一个换行加.*,如下所示:
.*
Q2 什么是一个原子操作?
微观世界中,如果定义原子是组成事物的最基本单元,那么就可理解为原子不能再分了。同理此处,正则的原子操作是指不能再被分割的正则表达式操作。
如正则中的+
指前面的一个原子操作出现至少1次。例如:66+
表示第一个字符为6,第二个字符6和第三个字符+联合起来表示至少出现1次字符6,因此综合起来至少要有2个6紧邻的串才能满足此正则表达式(下面会详细讲到)。
\w+
表示字母数字下划线中的任意一个字符(\w
指代的)至少出现1次,那么\w
就是一个原子操作。
因此,普通字符是原子,正则中的通用字符(下面会讲到)也是原子。大家记住原子这个概念。
Q3 怎么理解正则中的转义?
正则世界中,重新定义了几个新的转义字符。
一个转义字符\
+一个字符,转义后会改变原字符的意义,它不再是它,而是赋予一个新的含义。
例如,w
本身就是一个英文字符w
,没有其他任何含义。但是,前面加一个转义字符 \
后,含义发生重大改变,w
它不再是w
,而是\
要与w
连在一起,被解释器解释为匹配以下字符集合中的任意一个:
pat = '\w'
等于:
pat = '[0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz_]'
即匹配数字、大小写字母和下划线_
字符集合中的任意一个。
你看,一个通用转义字符\w
直接就指代上面这一大串,写法多么简便,同时在正则的世界里又经常被用到,故被称为:通用正则字符
类似的通用正则字符还有几个,下面也会讲到。做一件事前,把规则弄清,触类旁通,相信大家理解其他几个也没问题。
3 掌握最常用规则
为了更清晰的展示,咱们只涉及最常用的规则,一来缩短篇幅,二来降低大家学习曲线,三来一类问题掌握一个,触类旁通即可。
情况1:最普通查找
最普通查找就是需要找啥就写啥,没有使用正则的规则。如下是关于小说《灿烂千阳》中的一段话,从中找出单词friendship
,可能出现多次:
s = """
# Mariam is only fifteen
# when she is sent to Kabul to marry the troubled and bitter Rasheed,
# who is thirty years her senior.
# Nearly two decades later,
# in a climate of growing unrest, tragedy strikes fifteen-year-old Laila,
# who must leave her home and join Mariam's unhappy household.
# Laila and Mariam are to find consolation in each other,
# their friendship to grow as deep as the bond between sisters,
# as strong as the ties between mother and daughter.
# With the passing of time comes Taliban rule over Afghanistan,
# the streets of Kabul loud with the sound of gunfire and bombs,
# life a desperate struggle against starvation, brutality and fear,
# the women's endurance tested beyond their worst imaginings.
# Yet love can move a person to act in unexpected ways,
# lead them to overcome the most daunting obstacles with a startling heroism.
# In the end it is love that triumphs over death and destruction.
# A Thousand Splendid Suns is an unforgettable portrait of a wounded country and
# a deeply moving story of family and friendship.
# It is a beautiful, heart-wrenching story of an unforgiving time,
# an unlikely bond and an indestructible love.
"""
使用正则前,先导入re模块,再定义正则表达式,然后使用findall
方法找出所有匹配
import re
pat = 'friendship'
result = re.findall(pat,s)
print(result) # 共找到两处:
# ['friendship', 'friendship']
以上就是使用正则的最普通例子。如果要找出前缀为grow的单词,比如可能为grows, growing 等,最普通查找实现起来就不方便。
然而,借助于下面介绍的元字符、通用字符和捕获组合起来,便能应对解决复杂的匹配查找问题。
情况2:使用通用字符
在正则的世界里,通用字符指帮助我们更加简便的写出匹配规则的字符。
如上面文字,下面正则匹配串能找出以d开始,[a-z]表示的任意一个小写英文字符,{7}表示小写英文字符出现7次(下面情况3会说到),也就是匹配出来的子串长度为1+7=8:
pat = 'd[a-z]{7}'
result = re.findall(pat,s)
匹配结果为:
['daughter', 'desperat', 'daunting', 'destruct', 'destruct']
同理,模式串pat = 'd[a-z]{10}'
匹配的结果为:
['destruction', 'destructibl']
模式串pat = 'd[a-z]{11}'
匹配的结果为:
[ 'destructible']
你看,通用字符[a-z]
使用真方便,5个字符一下就表达了所有26个小写的字符,但是注意[a-z]
匹配26个小写字符的任意一个.
类似功能的通用字符还包括:
[A-Z] 匹配大写英文字母
[0-9] 匹配一个0-9之间的数字
还有更加强大的通用字符:
\s 匹配空白字符,如\n \t \b等
\w 匹配任意字母、数字、下划线
\d 匹配十进制数字0-9
而\S, \W, \D 分别对应 \s, \w, \d匹配字符集的补集,例如\S 的意思是匹配 \s 以外的其他任意字符。
情况3:使用元字符
元
的含义大家不妨理解为用来描述它后面事物的类,如元类用来创建描述类的类,元模型描述一个模型的模型,因此推而广之,元字符用来描述字符的字符。
理解以上后,你再看正则中使用最普遍的一个元字符 +
,它是用来描述前面一个原子出现次数的字符,表示前一个原子出现1次或多次都可。
例如,在寻找手机靓号时,正则表达式66+
,表示前一个原子6
至少出现1次,因此连上第一个6,表示电话号码中至少有两个66紧邻。因此,电话号码18612652166
、17566665656
都满足要求,而号码18616161616
不符合要求。
类似功能的元字符,还包括如下。功能相似,不再赘述:
* 前面的原子重复0次、1次、多次
? 前面的原子重复0次或者1次
+ 前面的原子重复1次或多次
{n} 前面的原子出现了 n 次
{n,} 前面的原子至少出现 n 次
{n,m} 前面的原子出现次数介于 n-m 之间
4 有个棘手的场景
了解以上规则后,我们能去完成很多匹配任务,比如一些字符串匹配任务;查找某个手机号是不是靓号;找到文字中出现某个模式的所有地方。
但是,使用正则还会经常遇到的一大场景。试想,从一个文件里提取出所有如下格式的链接,并全部导出来:
https://github.com/jackzhenguo/python-small-examples
https://gitbook.cn/gitchat/column/5e37978dec8d9033cf916b5d
截止目前,我们还不能完成这样的匹配任务。鉴于这种匹配任务确实很常见,因此你很有必要学会下面这项技能。
5 学会提取子串的技能
今天以我写过的《Python 60天》专栏中的一段文字,提取出里面的链接为例,阐述提取子串的实用性。
先贴上文字(有删减改动),将这段文字赋值给变量 urls
:
urls = """
基于 Python 的包更是枝繁叶茂,遍地开花,“Tiobe 编程语言排行榜”最新统计显示 Python 是增长最快的语言。![image-20200131192231967](https://images.gitbook.cn/2020-02-05-014719.png)接下来,与大家,还有远在美国做 AI 博士后研究的 Alicia,一起开始我们的 60 天 Python 探索之旅吧。所有的这些考虑,都是为了让大家在短时间内掌握 Python 技术栈,多一个生存的本领。拿到理想的 Offer 后,早日过上自己想要的生活。让我们开始吧。如下,按照是否为静态/动态语言,弱类型/强类型两个维度,总结常用的语言分类。![image-20200205155429583](https://images.gitbook.cn/2020-02-05-080211.png) ### 四大基本语法
"""
你可能很快写出如下的正则表达式:
# 元字符.表示匹配除\n字符外的任意一个字符
# 元字符*表示匹配前面一个原子0次或多次
pat = r'https:.*'
然后导入re
模块,使用findall
方法找出所有匹配:
import re
result = re.findall(pat,urls)
print(result)
运行结果显示如下,观察发现2个匹配,但是每个匹配链接都包括冗余字符,因此匹配错误:
['https://images.gitbook.cn
/2020-02-05-014719.png)','https://images.gitbook.cn
/2020-02-05-080211.png) ### 四大基本语法']
我们再稍微优化原正则表达式为:
# 添加 \) 表示待匹配子串以右括号结尾
pat = r'https:.*\)'
打印结果显示如下,结果确实好一点,但是依然包括右括号,结果还是错误的:
['https://images.gitbook.cn/
2020-02-05-014719.png)', 'https://images.gitbook.cn/
2020-02-05-080211.png)']
所以掌握提取子串的技能就很重要,实现提取子串也很简单,只需把想要返回的子串加上一对括号就行,如下所示:
# 把想要返回的子串外面添加一对括号pat = r'(https:.*)\)'
此时返回结果完全正确,无任何多余字符。想要返回的子串外面添加一对括号还有个专业叫法:捕获或分组。
6 使用捕获的注意事项
捕获功能非常实用,使用它需要区分一点,贪婪捕获和非贪婪捕获。前者指在满足匹配模式前提下,返回包括尽可能多的字符匹配模式;后者指满足匹配条件下,尽可能少的捕获。
我们伪造一个理想状况下的案例:
htmlContent = """<div><div><h2>这是二级标题</h2></div><div><p> 这是一个段落>/p></div></div>
"""
贪心捕获使用(.*)
,如下所示:
pat = r"<div>(.*)</div>"result = re.findall(pat,htmlContent)
结果为如下,尽可能长的捕获,而不是遇到第一个</div>
时就终止:
['<div><h2>这是二级标题</h2></div><div><p> 这是一个段落>/p></div>']
而非贪心捕获的正则表达式为<div>(.*?)</div>"
,如下:
pat = r"<div>(.*?)</div>"result = re.findall(pat,htmlContent)print(result)
结果为两个元素,遇到第一个</div>
时终止,然后继续捕获出第二子串:
['<div><h2>这是二级标题</h2>', '<p> 这是一个段落>/p>']
以上例子仅仅用作演示两者区别,实际的html结构含有换行符等,环境比上面要复杂的多,贪心和非贪心捕获的写法可能不会导致结果不同,但是我们依然需要理解它们的区别。
以上就是正则使用需要掌握的主要知识,整篇文章的结构总结如下:
1 学习正则的价值
2 正则学习前的几个准备
Q1 字符 `r`是干啥的?
Q2 什么是一个原子操作?
Q3 怎么理解正则中的转义?
3 掌握最常用规则
情况1:最普通查找
情况2:使用通用字符
情况3:使用元字符
4 有个棘手的场景
5 学会提取子串的技能
6 使用捕获的注意事项
掌握以上这些正则知识后,相信就能明白主要的正则原理了。具体到有些细节时大家可参考外部的正则可视化工具和检验工具,来验证一下自己写的正则表达式就行。
程序员专栏 扫码关注填加客服 长按识别下方二维码进群近期精彩内容推荐: 955 不加班的公司名单:955.WLB 终于稳了!2020年8月程序员工资最新统计 盘点 Python 10 大常用数据结构(上篇) 理解Java反射的正确姿势在看点这里好文分享给更多人↓↓
「Python 正则」使用专题总结相关推荐
- python编程a的x次方_「Python 面试」第四次更新
阅读本文大约需要 5 分钟. 15.说一说 GIL 前面有提到由于 Python 基于 C 语言编写的解释器中设置了一个 GIL 全局变量锁,该锁使得 Python 的多线程在处理 CPU 计算密集型 ...
- mysql数据字典生成器_「python技术」列表推导、生成器表达式和字典推导的差异及其示例
#开往春天新创作大赛# 前言 列表推导式构建列表的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列.自python2.7以后,列表推导和生成器表达式的概念就应用到了字典上,所以就有了字典推导, ...
- 「分布式系统理论」系列专题
如今互联网已经成为整个社会的基础设施,分布式系统并不是少数大公司的专属,所以分布式系统理论可能是你迟早需要掌握的知识. 如果你是程序员,相信这些文章你肯定能看懂:如果你不是程序员,相信这些能使你能更懂 ...
- 「分布式系统理论」系列专题整理
以下内容出自微信公众号 跨界架构师 ,有兴趣的朋友可以参考我的博客 DotNet微信公众号简介 进行关注. [数据一致性] <分布式系统关注点(1)--数据一致性>(入门理解「一致性」) ...
- 「Python 编程」编码实现网络请求库中的 URL 解析器
相信各位 Python 开发者都用过 Requests 库,有些朋友还用过 WebSockets 库.这里回顾一下它们的基本用法,例如使用 Requests 库向目标网站发出 GET 请求: impo ...
- 「Python入门」python环境搭建及VScode使用python运行方式
活动地址:CSDN21天学习挑战赛 文章目录 前言 一. python环境搭建 1.1 python下载安装 1.2 python安装 1.3 python环境变量配置 1.4 python版 ...
- 调用python_「Python 进阶」python 实现链式调用
#!/usr/bin/env Python3# -*- coding: utf-8 -*-# @Software: PyCharm# @virtualenv:workon# @contact: 104 ...
- 11个好用到起飞的「Python字典」知识点!
人生苦短,快学Python! 关于Python字典,算是Python中相当重要的数据类型了.在你学会基础知识后,字典这个概念,将会伴随着你后面的学习和工作. 因此,这里有几个相当重要的知识点,大家 ...
- python input输入多个变量_「Python 秘籍」1.2 解压可迭代对象赋值给多个变量
问题 需要从某个可迭代对象中分解出 N 个元素,但是这个可迭代对象的长度可能超过 N,这会导致出现"需要解包的值过多(too many values to unpack)"的异常. ...
最新文章
- hashmap原理_HashMap和HashTable底层原理以及区别
- 针对新手的Java EE7和Maven项目–第1部分–简单的Maven项目结构–父pom
- 没学过编程能学python吗_我没学过编程,能否学会Python?
- vue命令行错误处理
- 编程技能和做员工的技能——哪个更重要?
- Linux DNS | resolv.conf 配置dns解析,重启network丢失
- 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
- AMD因虚假宣传遭集体诉讼 向消费者赔偿1210万美元
- c语言牛顿方法,C语言编写牛顿迭代法的跟踪
- 法国政府正考虑采用开源软件
- H264之sps解析分辨率
- Linux下安装Scala
- 代理服务器的常用端口有哪些?
- ligerUi框架简单的表格展示
- Android状态栏禁止下拉异常分析
- 计算机视觉(三)图像拼接
- 微信 及支付宝 支付接口 功能
- 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)
- matlab区分连续波与脉冲,【求助】连续波多谱勒和脉冲波多谱勒的区别
- 每日一博 - 3D架构图 cloudcraft
热门文章
- 杭州java程序员好找工作吗,学习路线+知识点梳理
- java se的命令文件_Java SE的命令文件(java、javac、javadoc等)所在目录是___
- 【ES6语法】Object.assign合并数组及使用案例
- 为什么都用西门子PLC?有什么网关兼容西门子?
- 日常电脑办公快捷键小技巧
- php经纬度之间的距离计算公式,golang与php实现计算两个经纬度之间距离的方法
- CPU卡设计实例及程序设计(三十)ESAM过程密钥内部认证
- Gartner评估:众包将掀起IT服务市场的革命
- CVX——begin和end
- Problem 3: 人造卫星的高度