#CSDN21天学习挑战赛#Python入门之正则表达式-详细学习笔记(3)

开卷有益!如果你正在被正则表达式虐了千百遍依旧待它如初恋,请不要划走,这里或许有你想要的答案!

学无止境!希望往后余生​感恩今天的坚持!

活动地址:CSDN21天学习挑战赛

终于学习完re模块的re.match()函数,掌握了几种匹配模式的正则表达式写法,感兴趣的同学,欢迎查阅我的正则表达式-学习笔记(1)正则表达式-学习笔记(2),接下来我要紧锣密鼓地学习re模块的其他函数,并争取尽快完成课后练习。坚持!

**

学习日记

**
一、正则表达式学习要点

7、高级用法

①re.search()函数: 扫描整个字符串并返回第一个成功的匹配,匹配成功就返回一个匹配对象,否则返回None。(编号承接上一篇博文,下同)。

re.search(pattern, string, flags=0) : pattern 是用于匹配的正则表达式;string是被匹配的字符串;flags是标志位,用于控制正则表达式匹配的方式,如是否区分大小写(re.I)、多行匹配(re.M)等。

注意:re.match()与re.search()的区别

前者只匹配字符串的开头,如果字符串开头不符合正则表达式,则匹配失败,而返回None,而后者匹配整个字符串,直到找到一个匹配。

>>> import re
>>> line = "Cats are smarter than dogs"
#正则表达式r"(.*) are (.*?) (.+) (?:.*) "表示“子模式1 are 子模式2 子模式3 子模式,re.M|re.I 将标志设置为M和I即进行多行匹配并使匹配对大小写不敏感。
>>> searchobj = re.search(r"(.*) are (.*?) (.+) (?:.*)", line, re.M|re.I)
>>> if searchobj:
...     print("searchobj.group(): ", searchobj.group())
...     print("searchobj.group(1): ", searchobj.group(1))
...     print("searchobj.group(2): ",searchobj.group(2))
...     print("searchobj.group(3): ", searchobj.group(3))
...     print("searchobj.group(4): ",searchobj.group(4)) #第四个圆括号内的分组匹配的内容未被捕获,所以只有前3个分组数据
... else:
...     print("Nothing found!")
... 
searchobj.group():  Cats are smarter than dogs
searchobj.group(1):  Cats
searchobj.group(2):  smarter
searchobj.group(3):  than
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
IndexError: no such group

注意:该案例中的正则表达式中使用了特殊语法(),圆括号表示捕获分组,会把每个分组里的匹配值保存起来,从左向右以分组的左括号为标志,第一个出现的为组号1,第二个为2,以此类推,例如该案例中的searchobj.group(1)。与()对应的是(?:) ,二者唯一的区别是后者不会将匹配的值保存起来,因而无编号。

②re.findall()函数,在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的则返回空列表。

re.findall(pattern, string, flags=0) : pattern 是用于匹配的正则表达式;string是被匹配的字符串;flags是标志位,用于控制正则表达式匹配的方式,如是否区分大小写(re.I)、多行匹配(re.M)等。

注意:re.match()和re.search()仅匹配一次,而re.findall()是匹配所有
# 统计出python、c、c++相应文章阅读的次数,单个匹配模式,返回列表
>>> import re
#匹配数字,使用"\d+"或者r"\d+"
>>> result = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['9999', '7890', '12345']
>>> result = re.findall("\d+","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['9999', '7890', '12345']
#匹配字母和数字,使用"\w+" 或者r"\w+"
>>> result = re.findall("\w+","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['python', '9999', 'c', '7890', 'c', '12345']
>>> result = re.findall(r"\w+","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['python', '9999', 'c', '7890', 'c', '12345']
#匹配所有字符,\w+.+ 或者\w+.*
>>> result = re.findall(r"\w+.+","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['python = 9999, c = 7890, c++ = 12345']
>>> result = re.findall(r"\w+.*","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['python = 9999, c = 7890, c++ = 12345']
#仅匹配字母、数字和加号,r"\w+\+*"
>>> result = re.findall(r"\w+\+*","python = 9999, c = 7890, c++ = 12345")
>>> print(result)
['python', '9999', 'c', '7890', 'c++', '12345']
#多个匹配模式,返回元组列表
>>> result = re.findall(r"(\w+\+*) = (\d+)","python = 9999, c = 7890, c++ = 12345")
>>> print(result)                                                               [('python', '9999'), ('c', '7890'), ('c++', '12345')]
>>> result = re.findall(r"(\w+\+*)=(\d+)","python = 9999, c = 7890, c++ = 12345")
>>> print(result)                                                              
 []

注意:正则表达式的书写格式要与被匹配字符串的格式一致,否则会返回空值,比如上面案例中的多模式匹配中,被匹配的字符串python与=间有空格,书写正则表达式时=前后也要有空格。

③re.sub():将匹配到的数据进行替换

re.sub(pattern, repl, string, count=0, flags=0) : pattern 是正则表达式即模式字符串;repl是替换的字符串,也可以是一个函数;string是被查找替换的原始字符串;count设置模式匹配后替换的最大次数,默认值为0,表示替换所有的匹配;flags设置匹配的模式,数字形式。(标红为必选参数,标黑为可选参数)

>>> import re
>>>
>>> phone = "2004-959-559 # 这是一个电话号码"
# 删除#(注释)内容
>>> num = re.sub(r'#.*$', "", phone)
>>> print ("电话号码 : ", num)
电话号码 :  2004-959-559
 # 移除非数字的内容
>>> num = re.sub(r'\D', "", phone)
>>> print ("电话号码 : ", num)
电话号码 :  2004959559

④re.split(): 根据匹配进行切割字符串,并返回一个列表;

re.split(pattern,string,maxsplit=0,flags=0) : pattern 是匹配的正则表达式;string是被匹配的字符串;maxsplit设置分割次数,默认值是0,表示不限制次数,1表示分割1次;flags为标志位,用于控制正则表达式的匹配方式,如是否区分大小写(I)、多行匹配(M)等。

#re.split()的用法
>>> import re
#以:或空格切割字符串,maxsplit为默认值
>>> result = re.split(r":| ","info:xiaoZahang 33 shandong")
>>> print(result)
['info', 'xiaoZahang', '33', 'shandong']

#maxsplit=1
>>> result = re.split(r":| ","info:xiaoZahang 33 shandong",maxsplit=1)
>>> print(result)
['info', 'xiaoZahang 33 shandong']

#maxsplit=2
>>> result = re.split(r":| ","info:xiaoZahang 33 shandong",maxsplit=2)
>>> print(result)
['info', 'xiaoZahang', '33 shandong']

8、特殊语法

①(?:pattern): ()表示捕获分组,会把每个分组里匹配的值保存起来,从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。而(?:)表示非捕获分组,和捕获分组的区别在于不会将匹配的值保存起来。 详见上文re.search案例。

②(?=pattern):正向肯定预查,匹配pattern前面的位置,但不捕获pattern,为非获取匹配。匹配成功即可捕获pattern前面的字符串,匹配失败则报错。

>>> import re
#(?=pattern)表示正向肯定预查
>>> result = re.search("Windows(?=95|98|NT|2000)","Windows2000")
>>> print(result.group())
Windows

>>> result = re.search("Windows(?=95|98|NT|2000)","Windows3.1")
>>> print(result.group())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

③(?!pattern): 正向否定预查,匹配pattern前面的位置,在任何不匹配pattern的字符串开始处匹配查找pattern千的字符串,即匹配失败捕获pattern前的字符串。也是非获取匹配。与(?=pattern)相反。

>>> import re

>>> result = re.search("Windows(?!95|98|NT|2000)","Windows2000")
>>> print(result.group())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
 
>>> result = re.search("Windows(?!95|98|NT|2000)","Windows3.1")
>>> print(result.group())
Windows

9、python贪婪和非贪婪

正则表达式中使用的通配符.在从左到右匹配字符时会尽量“捕获”字符串。这样的字符就是贪婪字符,数量词在python中默认是贪婪的,总是尝试匹配尽可能多的字符;非贪婪则相反。在*、?、+、{m,n}后面加上?可以使贪婪变成非贪婪。

>>> import re

>>> str = 'www.baidu.com/path'

# ‘+’贪婪模式,匹配1个或多个
>>> ret = re.match(r'\w+', str)
>>> print(ret.group())
www

# ‘+?’非贪婪模式,匹配1个
>>> ret = re.match(r'\w+?', str)
>>> print(ret.group())
w

# {2,5}贪婪模式最少匹配2个,最多匹配5个
>>> ret = re.match(r'\w{2,5}', str)
>>> print(ret.group())
www

# {2,5}?非贪婪模式,匹配两个
>>> ret = re.match(r'\w{2,5}?', str)
>>> print(ret.group())
ww

10、r的作用

python中反斜杠\在正则表达式中为转义符 ,如果你要匹配的字符中包含\,那么使用正则表达式里需要4个"\", 十分容易出错。Python中的原生字符串r''很好的解决这个问题,因为r"\\"就可以直接匹配文本中的\,其中第一个\是转义符,转义第二个\。

>>> import re
>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'

>>> print(mm)
c:\a\b\c
>>> re.match("c:\\\\",mm).group()
'c:\\'

>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\

>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a

>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a

>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

二、实战案例

练习1:从下面的字符串中提取文本

<div>
<p>岗位职责:</p>
<p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>
<p><br></p>
<p>必备要求:</p>
<p>良好的自我驱动力和职业素养,工作积极主动、结果导向</p>
<p>&nbsp;<br></p>
<p>技术要求:</p>
<p>1、一年以上 Python 开发经验,掌握面向对象分析和设计,了解设计模式</p>
<p>2、掌握HTTP协议,熟悉MVC、MVVM等概念以及相关WEB开发框架</p>
<p>3、掌握关系数据库开发设计,掌握 SQL,熟练使用 MySQL/PostgreSQL 中的一种<br></p>
<p>4、掌握NoSQL、MQ,熟练使用对应技术解决方案</p>
<p>5、熟悉 Javascript/CSS/HTML5,JQuery、React、Vue.js</p>
<p>&nbsp;<br></p>
<p>加分项:</p>
<p>大数据,数理统计,机器学习,sklearn,高性能,大并发。</p>
</div>

#参考答案:re.sub(r"<[^>]*>|&nbsp;|\n","",test_str)

练习2:提取img标签中的图片链接地址

#字符串
<img data-original="https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" src="https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" style="display: inline;">

#参考答案
re.search(r"https://.*?\.jpg",test_str)

练习3:排除指定字符串

使用^(?!.*abc).*$,其中abc为要排除的字符串

import re

partten = r'^(?!.*abc).*$'
strs = ['abc222', '111abc222', '111abc', 'defg']
for i in strs:
    print(re.findall(partten, i))
  • ^和$表示从字符串开头开始,匹配到结尾;
  • (?!.*)表示排除形如abc的部分;
  • 后面的.*表示abc后面还可以有内容 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值