(十六)re模块
正则表达式并不是Python的一部分,本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言。正则表达式是用于处理字符串的强大工具,很多编程语言都支持正则表达式的语法。
字符匹配分为普通字符和元字符:
普通字符:精确匹配
>>> re.findall('nick','asdanickkyuj')
['nick']
元字符:. ^ $ * + ? { } [ ] | ( ) \
. 通配符,匹配任意除换行符"\n"外的一个字符
>>> re.findall('n..k','asdanerkyuj')
['nerk']
^ 以什么开头
>>> re.findall('^n..k','asdanickkyuj') #中间有nick是无法匹配的
[]
>>> re.findall('^n..k','nickkyuj') #必须是从头开始匹配
['nick']
$ 以什么结尾
>>> re.findall('n..k$','nickkyuj')
[]
>>> re.findall('n..k$','nickkyujnfdk') #必须是从尾匹配
['nfdk']
* 重复匹配上一个字符0到无穷大次
+ 重复匹配上一个字符1到无穷大次
? 重复匹配上一个字符0到1次
>>> re.findall('yus*','nickkyusssss') #s*匹配5个s
['yusssss']
>>> re.findall('yus+','nickkyusssss') #s+匹配5个s
['yusssss']
>>> re.findall('yus*','nickkyu') #s*匹配0个s
['yu']
>>> re.findall('yus+','nickkyu') #s+无法匹配
[]
>>> re.findall('yus?','nickkyu') #s?匹配0个s
['yu']
>>> re.findall('yus?','nickkyusssss') #s?匹配一个s
['yus']
{} 重复匹配上一个字符自定义的次数
{0,}相当于* {1,}相当于+ {0,1}相当于?
>>> re.findall('yus{0,6}','nickkyusssss') #匹配0~6之间任意次数
['yusssss']
>>> re.findall('yus{0,1}','nickkyusssss') #相当于? 匹配一次
['yus']
>>> re.findall('yus{6}','nickkyusssss') #指定匹配6次,无法匹配
[]
注意:前面的*,+,?等都是贪婪匹配,也就是尽可能多的匹配,后面加?号使其变成惰性匹配
>>> re.findall('yus*','nickkyusssss') #贪婪匹配
['yusssss']
>>> re.findall('yus*?','nickkyusssss') #惰性匹配
['yu']
[] 字符集,表示或的关系。在中括号里的字符,任选其一挨个匹配
>>> re.findall('q[ab]','asdqaerqbsd') #qa和qb挨个匹配
['qa', 'qb']
>>> re.findall('q[a*]','asdqaaaerqbsd') #qa和q*挨个匹配
['qa']
>>> re.findall('q[.*+]','a.dqaaq+aerqbsd') #q. q* q+挨个匹配
['q+']
注意:在字符集[]里是没有元字符的概念的,. * + 这些仅仅就是字符
除了这三个:- ^ \
- 表示范围,从xx到xx挨个匹配
>>> re.findall('q[a-z]','a.dqaaq+aerqbsqqd')
['qa', 'qb', 'qq']
>>> re.findall('q[a-z]*','a.dqaaqaerqbsqqd') #[a-z]*匹配任意字母任意次
['qaaqaerqbsqqd']
>>> re.findall('q[0-9]*','a.dqsd9') #*匹配了0次,就匹配了一个q
['q']
^ 注意这里是在[]里的^,不是上文描述的^,表示非
>>> re.findall('q[^0-9]','a.dqsd9')
['qs']
>>> re.findall('q[^a-z]','a.dqsd9')
[]
需求:匹配 6+(3*7+2-(5-3))中的(5-3)
思路是:匹配括号开始,匹配括号结束,中间却又没有括号
>>> re.findall('\([^()]*\)','6+(3*7+2-(5-3))') #\(和\)是转义符表示() [^()]*表示没有()的任意个字符
['(5-3)']
\ 转义符,后面详细说明
>>> re.findall('[\d]','123abc')
['1', '2', '3']
\ 转义符
反斜杠后边跟元字符去除特殊功能,比如\.
反斜杠后边跟普通字符实现特殊功能,比如\d
\ 加普通字符实现特殊功能:
\d 匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b 匹配一个特殊字符边界,比如空格 ,&,#等
\d与\D :
>>> re.findall('\d','6+(31*7+23-(5-3))') #匹配单个数字
['6', '3', '1', '7', '2', '3', '5', '3']
>>> re.findall('\d+','6+(31*7+23-(5-3))') #匹配多个数字
['6', '31', '7', '23', '5', '3']
>>> re.findall('\D+','6+(31*7+23-(5-3))') #匹配多个非数字
['+(', '*', '+', '-(', '-', '))']
\s与\S :
>>> re.findall('\s','hello world!')
[' ']
>>> re.findall('\S','hello world!')
['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '!']
\w与\W :
>>> re.findall('\w','hello_world!#')
['h', 'e', 'l', 'l', 'o', '_', 'w', 'o', 'r', 'l', 'd']
>>> re.findall('\W','hello_world!#')
['!', '#']
\b:
需求,要匹配 'hello I am LILY' 中的第一个I。思路是第一个I后面是空格,用\b
>>> re.findall('I\b','hello I am LILY')
[]
>>> re.findall(r'I\b','hello I am LILY')
['I']
>>> re.findall('I\\b','hello I am LILY')
['I']
正则表达式re是一门独立的编程语言,在re中\b有特殊的意义(匹配一个特殊字符边界),然而,在Python中\b也有特殊的意义(不知道是啥),当Python解释器拿到\b,会转义为Python规定的那个特殊意义(不知道是啥),再丢给re,那re肯定不认识,所以无法匹配。
第一种方法:r'I\b'
r 代表的意思是: raw,raw string是原生字符串的意思。加上r表示里面的字符串不做任何转义,直接丢给re,所以r'I\b'的意思是Python解释器不做任何转义,将'I\b'交给re,re再去转义为I+一个特殊字符边界(这里是一个空格),成功匹配第一个I
第二种方法:'I\\b'
Python解释器将'I\\b'转义为'I\b'丢给re,re拿到'I\b',re再去转义为I+一个特殊字符边界(这里是一个空格),成功匹配第一个I
同理:要匹配c\m
>>> re.findall('c\\m','ac\ms')
[]
>>> re.findall(r'c\\m','ac\ms')
['c\\m']
>>> re.findall('c\\\\m','ac\ms')
['c\\m']
要么r'c\\m',Python不转义,re把c\\m转义为c\m,匹配成功
要么'c\\\\m',Python转义为c\\m,re把c\\m转义为c\m,匹配成功
如上两个例子,使用转义符时,当Python里也有他自己的特殊转义规则时,要么直接加r让Python不做处理,要么处理好Python和re的两层转义。
\ 加元字符去除特殊功能:
>>> re.findall('www.baidu','www.baidu') #.是元字符,匹配'.',模糊匹配成功
['www.baidu']
>>> re.findall('www\.baidu','www.baidu') #\.是普通字符,匹配'.',精确匹配成功
['www.baidu']
>>> re.findall('www*baidu','www*baidu') #*是元字符,重复匹配前面的'w',无法匹配后面的'*'
[]
>>> re.findall('www\*baidu','www*baidu') #\*是普通字符,匹配'*',精确匹配成功
['www*baidu']
| 表示或
>>> re.findall('ca|fr','sca7fr89') #ca或fr
['ca', 'fr']
>>> re.findall('ca|\d','sca7fr89') #ca或数字
['ca', '7', '8', '9']
>>> re.findall('ca|\D','sca7fr89') #ca或非数字
['s', 'ca', 'f', 'r']
() 分组
>>> re.findall('abc+','abcccc') #匹配c,1到无穷次
['abcccc']
>>> re.findall('(abc)+','abcccc') #abc作为一个整体去匹配,1到无穷次
['abc']
命名分组
>>> re.search('(?P<name>[a-z]+)(?P<age>\d+)','nick20tom24jack28') #两个分组,name和age
<_sre.SRE_Match object; span=(0, 6), match='nick20'> #search()方法只匹配第一个符合的结果,返回一个对象
>>> re.search('(?P<name>[a-z]+)(?P<age>\d+)','nick20tom24jack28').group() #group()拿到匹配的结果
'nick20'
>>> re.search('(?P<name>[a-z]+)(?P<age>\d+)','nick20tom24jack28').group('name') #group('name')拿到第一个分组name的值nick
'nick'
>>> re.search('(?P<name>[a-z]+)(?P<age>\d+)','nick20tom24jack28').group('age')
'20'
(?P<name>[a-z]+)是一个命名分组,?P<>是固定写法,<>里是自定义的命名,后面的[a-z]+才是实际要匹配的字符
search()方法只匹配第一个结果就返回一个对象,这个对象的group()方法就能拿到匹配的结果nick20,其中nick就是name,22就是age,如果用group('name')就能拿到nick,这就是分组的好处,这种方法在以后开发时常用于匹配网址url。
re模块下的常用方法
re.findall(' ',' ') #返回所有满足匹配条件的结果,放在列表里。
re.search(' ',' ').group() #函数会在字符串内查找模式匹配,直到找到第一个匹配结果然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
re.match(' ',' ').group() #同search,不过只在字符串开始处进行匹配。
>>> re.match('\d+','abc22') #开头没有数字,所以不匹配
>>> re.match('\d+','22abc') #开头有数字,匹配22
<_sre.SRE_Match object; span=(0, 2), match='22'>
>>> re.match('\d+','22abc').group()
'22'
re.split(' ',' ') #分割字符串,类似于string里面的split(),如果是[]字符集,就按照里面的字符挨个分割
>>> re.split('[ab]','hanbo') #先按'a'分割得到'h'和'nbo',再对'h'和'nbo'按'b'分割得到'h', 'n', 'o'
['h', 'n', 'o']
>>> re.split('[ab]','abo') #先按'a'分割得到''和'bo',再对''和'bo'按'b'分割得到'','','o'
['', '', 'o']
re.sub('被替换的字符串','替换成什么字符串','待处理的整个字符串',替换几次) #替换字符串
>>> re.sub('\d+','B','g23h578') #匹配多个数字
'gBhB'
>>> re.sub('\d','B','g23h578') #匹配单个数字
'gBBhBBB'
>>> re.sub('\d','B','g23h578',2) #匹配单个数字,替换两次
'gBBh578'
re.subn() #与sub的功能和参数都一样,唯一的不同是返回值:一个元组,其中第一个元素是处理后的结果,第二个元素是替换了几次
>>> re.subn('\d','B','g23h578',2)
('gBBh578', 2)
>>> re.subn('\d','B','g23h578',)
('gBBhBBB', 5)
re.compile(' ') #另一种写法而已,参数是匹配的规则,返回给一个对象,然后用这个对象去findall()或者search()
>>> res = re.compile('\d+')
>>> res.findall('asd123ds')
['123']
>>> res.search('as12kj34re')
<_sre.SRE_Match object; span=(2, 4), match='12'>
>>> res.search('as12kj34re').group()
'12'
这么做的好处是:用'\d+'去处理多个字符串的时候,可以用res直接去处理,效率高。
re.finditer(' ',' ') #用法与findall()一模一样,只是不返回一个数组,而是一个迭代器
>>> re.findall('\d+','as12kj34re')
['12', '34']
>>> re.finditer('\d+','as12kj34re')
<callable_iterator object at 0x0000029D51E6DB00>
>>> res = re.finditer('\d+','as12kj34re')
>>> next(res).group() #迭代器用next()迭代取值
'12'
>>> next(res).group()
'34'
>>> next(res).group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
这么做的好处是:通常我们处理的字符串都很庞大,如果都返回数组就要放入内存,消耗系统资源,而返回迭代器就可以想要什么数据只拿那个数据。
补充:
>>> re.findall('www\.(baidu|taobao)\.com','www.taobao.com')
['taobao']
当在匹配规则中使用()分组,Python解释器将默认优先匹配()中的字符串规则,而忽略外面的字符串规则
>>> re.findall('www\.(?:baidu|taobao)\.com','www.taobao.com')
['www.taobao.com']
?:就是去掉这个默认的优先级,不忽略外面的字符串规则
(十六)re模块的更多相关文章
- Python爬虫(十六)_JSON模块与JsonPath
本篇将介绍使用,更多内容请参考:Python学习指南 数据提取之JSON与JsonPATH JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它是的人们很容易 ...
- jQuery 源码分析(十六) 事件系统模块 底层方法 详解
jQuery事件系统并没有将事件监听函数直接绑定到DOM元素上,而是基于数据缓存模块来管理监听函数的,事件模块代码有点多,我把它分为了三个部分:分底层方法.实例方法和便捷方法.ready事件来讲,好理 ...
- Python学习日记(十六) time模块和random模块
time模块 python表示时间的三种方式:时间戳.元祖(struct_time).格式化时间字符串 三种格式之间的转换: 1.时间戳 就是从1970年1月1日0点0分0秒开始按秒计算的偏移量,时间 ...
- 第三百二十六节,web爬虫,scrapy模块,解决重复ur——自动递归url
第三百二十六节,web爬虫,scrapy模块,解决重复url——自动递归url 一般抓取过的url不重复抓取,那么就需要记录url,判断当前URL如果在记录里说明已经抓取过了,如果不存在说明没抓取过 ...
- STC8H开发(十六): GPIO驱动XL2400无线模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- linux基础-第十六单元 yum管理RPM包
第十六单元 yum管理RPM包 yum的功能 本地yum配置 光盘挂载和镜像挂载 本地yum配置 网络yum配置 网络yum配置 Yum命令的使用 使用yum安装软件 使用yum删除软件 安装组件 删 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
- 菜鸟玩云计算之十六:Ubuntu14.04上创建的虚拟机迁移到RHEL6.4
菜鸟玩云计算之十六:Ubuntu14.04上创建的RHEL6.4虚拟机迁移到RHEL6.4主机上 RHEL6.4 Server作为虚拟机的HOST,执行以下的命令检查配置和安装相关软件: # egre ...
- 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...
- Linux时间子系统之(十六):clockevent
专题文档汇总目录 Notes:介绍struct clocke_event_device及其功能feature.模式:触发event接口clockevents_program_event:clockev ...
随机推荐
- React Native学习记录
1.端口问题 在调试的时候,监听的是8081端口.如果被占用,会报错,并且在reload的时候导致app直接崩掉. 2.插件网站收集 https://nativebase.io/ https://js ...
- Python 学习笔记 之 03 - 函数总结
函数总结 最基本的一种代码抽象的方式. 定义函数 使用def语句进行定义, return进行函数返回. 一旦执行导return,函数就执行完毕. 即使函数未指定retur ...
- Shell脚本命令常用技巧
如果一个命令只有一次输出,但想持续观察输出变化,使用watch -d -n1 'df -h'可行,df -h输出一次硬盘使用情况,用上面指令可以持续观察.-d表示相邻输出如果有差异要高亮标记,-n1表 ...
- vue第十五单元(熟练使用vue-router插件)
第十五单元(熟练使用vue-router插件) #课程目标 1.掌握路由嵌套 2.掌握导航守卫 #知识点 #一.路由嵌套 很多时候,我们会在一个视口中实现局部页面的切换.这时候就需要到了嵌套路由. 也 ...
- matplotlib的学习14-图中图
# 导入pyplot模块 import matplotlib.pyplot as plt # 初始化figure fig = plt.figure() # 创建数据 x = [1, 2, 3, 4, ...
- Promise对象,究竟为何物?
Promise对象 一.什么是Promise? Promise是一种异步操作的解决方案,将写法复杂的传统的回调函数和监听事件的异步操作,用同步代码的形式表达出来. Promise避免了多级异步操作的回 ...
- Redis缓存穿透和缓存雪崩的面试题解析
前段时间去摩拜面试,然后,做笔试的时候,遇到了几道Redis面试题目,今天来做个总结.捋一下思路,顺便温习一下之前的知识,如果对您有帮助,左上角点下关注 ! 谢谢 文章目录 缓存穿透 缓存雪崩 大家都 ...
- Flink 反压 浅入浅出
前言 微信搜[Java3y]关注这个朴实无华的男人,点赞关注是对我最大的支持! 文本已收录至我的GitHub:https://github.com/ZhongFuCheng3y/3y,有300多篇原创 ...
- JXL封装不能使用static关键字问题
最近要做一个Excel导出的功能,由于文件不大,涉及到了很多Excel表格样式和公式计算,我采用了JXL的方式导出.由于逻辑大多是金额,所以我在封装JXL的时候写了两个静态final变量,代码如下: ...
- Unity使用小剧场—创建的按钮On Click()只有MonoScript怎么办
前言: 在游戏开发过程中遇到了一些小问题,以后都放到小剧场里,今天介绍怎么给按钮赋予方法并解决标题所述问题. 步骤: 1. 不管怎么说,先新建一个按钮 右键场景-[UI]-[Button] 这里会自动 ...