正则函数

match、search、findall、finditer、split、sub

返回一个对象:match、search、finditer

返回一个列表:findall、split

其中match、search与findall都有两个匹配方式:简单匹配和分组匹配

1、match

格式

match(正则表达式,字符串,标志位)

match( r'xxx' , str , flags = 0 )

一般只用到了前两个参数

match( r'XXX' , str )

flags(标志位)用于修改正则表达式的匹配方式,常见的工作方式:

re.I    使匹配对大小写不敏感

re.L    做本地化识别(local-aware)匹配

re.M    多行匹配,影响^和$,不匹配换行符

re.S    使.匹配包含换行在内的所有字符(可能是改变元字符 . 的用法?)

……

匹配结果

简单匹配下,匹配成功返回一个Match对象,失败则返回None。

Match对象的group()返回匹配到的结果字符串(与正则表达式字符串完全对应的字符串)

常用的判断方法是:

import re

if re.match(正则表达式 , 测试字符串):
print('OK!')
else:
print('Failed!')

如果match的第一个参数是一个没有加任何正则表达式的规则的字符串,则默认匹配从测试字符串的开头匹配参数一中的字符串,匹配到了就返回一个Match对象,该Match对象的group()即为参数一中的字符串,group()和group(0)的效果相同。匹配不到就返回None。

例子

#单纯字符串匹配,只从开头匹配
#result1从开头能匹配上
result1=re.match('abc','abcdef')
#result2从开头匹配不上
result2=re.match('abc','1abc') result1
<re.Match object; span=(0, 3), match='abc'>
result1.group()
'abc'
print(result2)
None

分组匹配下:

m=re.match(带括号的正则表达式 , 字符串)

通过group和groups方法提取分组结果

举个例子说明如下:

import re

m=re.match(r'^(\d{3})-(\d{3,8})$','010-12345')

m.group(0)
'010-12345'
m.group(1)
'010'
m.group(2)
'12345'
m.groups()
('010', '12345')

group(0)是原始字符串,group(1)、group(2)、……表示第1、2、……个子串。此外groups()是一个包含了所有子串的tuple。

补充一个冷门知识点:

正则表达式中的?P<A1>格式:用于groupdict()方法以及之后模块6的替换sub()方法中

直接上例子:

str='hello world'
re1=re.compile(r'(?P<n1>h)(?P<n2>\w+)')
ret=re1.match(str) ret.groupdict()
{'n1': 'h', 'n2': 'ello'}

所以正则式中的?P<n2>\w+的意思就是声明了一个dict,其中一个Key-Value对为:Key为n2,Value为\w+匹配的结果。

通过groupdict()来查看这个dict。

2、search

re.search()方法扫描整个字符串,并返回第一个成功的匹配。如果匹配失败,则返回None。

与re.match()方法的区别:re.match()要求必须从字符串的开头进行匹配,如果字符串的开头不匹配,整个匹配就失效了。

re.search()并不要求从字符串的开头进行匹配,也就是说,正则表达式可以是字符串的一部分(与之区别的是match就要求正则表达式必须从头到尾完全与字符串匹配,否则就是不匹配)

格式与match类似:

re.search(正则表达式,字符串,标志位)

re.search(r'',str,flags=0)

例一:提取'Hello 123456789 Word_This is just a test 666 Test'中的数字

str='Hello 123456789 Word_This is just a test 666 Test'
re6=r'(\d+).*?(\d+)' #必须是非贪婪匹配*? 否则后一个()只会接收最后一个数字
ret=re.search(re6,str)
if ret:
for i in ret.groups():
print (i)
else:
print(ret)

结果:

123456789
666

例二:上例的字符串,只用(\d+)去匹配

str='Hello 123456789 Word_This is just a test 666 Test'
re7=r'(\d+)'
ret=re.search(re7,str)
if ret:
for i in ret.groups():
print (i)
else:
print(ret) #结果
123456789

重要!!!!!!!

正则串中有多少个括号(),匹配结果的groups中就有几个结果。另外,由于search只取第一个成功匹配的结果,所以即使后边还有可以匹配成功的字符串,也不计入groups中

3、findall

search只会返回第一个成功匹配的字符串,而findall会将所有匹配到的字符串,都放置在同一个List中。

①优先匹配原则

findall的正则式中的括号是优先匹配和分组匹配的标志,一个括号对应一个组。

findall与search、match等不同的是,它会优先取组里的内容,但是可以使用?:来关闭。

str='123 www.bing.com123www.google.com123'

re81=r'www.(bing|google).com'
re82=r'www.(?:bing|google).com' ret1=re.findall(re81,str)
ret2=re.findall(re82,str)
print(ret1,'\n',ret2) ['bing', 'google']
['www.bing.com', 'www.google.com']

当正则式为re81——www.(bing|google).com时,会只匹配括号中的内容,即bing|google,相当于正则式就是括号中的内容(★★★★),即 re81=r'bing|google'

如果想取消优先匹配,只需在(后边加上?:即可。

由于括号常与或|关联,所以在正则式中用到或(A|B)的格式时,一定要注意关闭优先匹配?:,然后再匹配,这样就能发挥或的作用了,就像上边的正则式re82。

这一点的总结:

a、当正则没有分组就是返回整个正则式的匹配

b、当正则式中有一个分组就是这个分组的匹配

c、多个分组的匹配方式与一个分组相同,但结果会将分组装到tuple中返回

关于c的举例:

content= 'email:12345678@163.com,...' \
'email:2345678@163.com,...' \
'email:345678@163.com' re10=re.compile(r'(\d+)@(\w+.com)')
ret_findall=re10.findall(content)
print(ret_findall)
[('12345678', '163.com'), ('2345678', '163.com'), ('345678', '163.com')]

因此当我们同时需要整个正则和各个分组的匹配,我们需要为整个正则式加括号。

re10=re.compile(r'((\d+)@(\w+.com))')

[('12345678@163.com', '12345678', '163.com'), ('2345678@163.com', '2345678', '163.com'), ('345678@163.com', '345678', '163.com')]

对整个正则式的匹配结果,是返回tuple的第一个元素。

②匹配顺序

一旦有字符被匹配到,就会把匹配到的字符拿走,然后再匹配剩下的字符,如下:

#匹配顺序
str='a2b3c4d5'
re8=r'\d+\w\d+'
ret=re.findall(re8,str)
print(ret) ['2b3', '4d5']

③匹配空值

当匹配规则为空''时,如果没有匹配到也会把空值放到结果中:

re8=r''
str='abcdef'
ret=re.findall(re8,str)
print(ret) ['', '', '', '', '', '', '']

所以写Python正则时,要尽量使正则不为空,所以正则式为一个单字符+元字符的形式时,尽量用+而不是*符(因为*表示{0,}——任意个字符)

下面给出一个推荐和不推荐的写法的例子

str='alex'
ret1=re.findall(r'\w+',str) #推荐用 +
ret2=re.findall(r'\w*',str) #不推荐用 *
print(ret1,'\n',ret2) ['alex']
['alex', '']

当然这里的推荐与不推荐,仅仅针对findall,无关match和search

④贪婪与非贪婪

这点与match、search倒是类似,非贪婪匹配也是在+后写个?,构成+?

例如:

ret1=re.findall(r'\d+','a23b')
ret2=re.findall(r'\d+?','a23b')
ret3=re.findall(r'a(\d+?)b','a23b')
print(ret1,'\n',ret2,'\n',ret3) ['23']
['2', '3']
['23']

值得注意的是第三种情况,当括号()位于a,b之间的时候?失效,整个匹配又变成了和第一种情况一样的贪婪匹配。

最后对于findall的总结:

1、findall会查找所有匹配结果,放在最后的List中

2、有字符串匹配到后,就会在原串中把匹配到的子串删去,再从剩下的串中匹配。

3、findall的()代表优先匹配,而不是分组匹配,更何况,findall本身就不支持分组匹配。

findall正则式里有括号,可以把该正则式只看做括号中的内容(详见①优先匹配)

4、非贪婪匹配如果夹在两个字符之间,就会失效变为贪婪匹配(详见④贪婪匹配)。

4、finditer

返回一个可迭代的MatchObject类型的Iterator:

p=re.compile(r'\d+')
str='12 dsnjfkbsfj1334jnkb3kj242'
w1=p.finditer(str)
w2=p.findall(str)
print(w1)
print(w2) <callable_iterator object at 0x000002553AD77408>
['12', '1334', '3', '242']

访问w1的方法是通过for循环迭代器实现:

for ret in w1:
print(ret.group(),ret.span()) 12 (0, 2)
1334 (14, 18)
3 (22, 23)
242 (25, 28)

MatchIterator对象的方法:

group()方法可以得到匹配到的结果;在有分组的情况下group(n)表示第n个分组的匹配结果

span()方法得到一个tuple,其中存储匹配结果在原串中的(首下标,尾下标+1)。

findall与finditer

学习自:https://blog.csdn.net/naipeng/article/details/94744621

相同点:

二者都可以获取所有匹配结果

不同点:

findall返回一个list;finditer返回一个MatchObject类型的Iterator

这也就决定了:

提取finditer的信息,要通过for循环,并调用每个对象的group()方法;提取findall的信息可以直接print,或是其他list操作方法

content= 'email:12345678@163.com,
email:2345678@163.com,
email:345678@163.com
'

需求1:提取所有邮箱信息,不需要分组

re10=re.compile('\d+@\w+.com')
ret1_finditer=re10.finditer(content)
for i in ret1_finditer:
print(i.group()) ret2_findall=re10.findall(content)
print(ret2_findall)
12345678@163.com
2345678@163.com
345678@163.com
['12345678@163.com', '2345678@163.com', '345678@163.com']

需求2:提取出所有电话号码和邮箱类型

re10=re.compile(r'(\d+)@(\w+.com)')
ret_finditer=re10.finditer(content)
ret_findall=re10.findall(content)
for i in ret_finditer:
print(i.group(1),' ',i.group(2)) print(ret_findall)
12345678   163.com
2345678 163.com
345678 163.com
[('12345678', '163.com'), ('2345678', '163.com'), ('345678', '163.com')]

可见,当有分组时,finditer通过group(n)访问第n个分组的匹配结果;而findall则是把每个组查找的结果综合为一个tuple。

5、分割——split

格式:

re.split(正则式,待分割字符串,maxsplit=0 , flags=0)

参数maxsplit——最大分割次数

返回一个list

①优先匹配原则

由于split和findall返回的都是所有元素的列表,因此他和findall一样具有优先匹配的特性。

②有组与无组

有组时,结果会包含处于分割位置的字符串,即分成[ 分割位置前 , 分隔位置处 , 分割位置后]

无组时,结果不含处于分割位置的字符串,即分成[ 分割位置前 , 分割位置后 ]

origin = 'hello alex bcd abcd lge acd 19'
#无组
re1=re.compile(r'a\w+')
#有组
re2=re.compile(r'(a\w+)')#组中包含a
re3=re.compile(r'a(\w+)')#组中不含a
print(re1.split(origin))
print(re2.split(origin))
print(re3.split(origin))

结果:

['hello ', ' bcd ', ' lge ', ' 19']
['hello ', 'alex', ' bcd ', 'abcd', ' lge ', 'acd', ' 19']
['hello ', 'lex', ' bcd ', 'bcd', ' lge ', 'cd', ' 19']

连续n个匹配串

如果分割位置在开头或者最后,则分割后的第一个分割串之前或者最后一个分割串之后会多一个空串;

如果开头或者结尾,有n个匹配串,就会在分割后的list中的开头或结尾多n个空串。

而在中间的连续n个匹配串,则会多n-1个空串(当只有一个匹配串时,没有空串),这一点也适用于[](见下文例子中的origin4和re2的组合)

origin1='aabaadecacaa'#首尾2个匹配串
origin2='abaadecaca' #首尾1个匹配串 中间连续2个匹配串
origin3='caaac' #中间连续3个匹配串
origin4='cabac' #用[]间接造成中间连续3个匹配串
re1=re.compile(r'a')
re2=re.compile(r'[ab]')
print(re1.split(origin1))
print(re1.split(origin2))
print(re1.split(origin3))
print(re2.split(origin4)) ['', '', 'b', '', 'dec', 'c', '', '']
['', 'b', '', 'dec', 'c', '']
['c', '', '', 'c']
['c', '', '', 'c']

消除串中所有异常字符

如果要消去一个字符串中的所有异常字符呢?用[]把全部异常字符包括就可以了。

比如str='a,b  ; c . e f  ,f g'

异常字符就包括:, ; . 空格

则我们的正则表达式就可以写为:r'[,;\.\s]+'

re1=re.compile(r'[,;\.\s]+')
re1.split(str) ['a', 'b', 'c', 'e', 'f', 'f', 'g']

6、替换——sub

格式:re.sub(被替换子串正则式,替换为的子串,str[ , count=0])

count为替换的次数,默认为0全部替换

返回替换后str

str='I get A,I got B,I gut C'
substr='hava'
re12=re.compile('g.t')
ret=[]
ret.append(re12.sub(substr,str))
ret.append(re12.sub(substr,str,count=0))
ret.append(re12.sub(substr,str,count=2))
ret.append(re12.sub(substr,str,3))
ret.append(re12.sub(substr,str,2))
for i in range(len(ret)):
print(ret[i])
I hava A,I hava B,I hava C
I hava A,I hava B,I hava C
I hava A,I hava B,I gut C
I hava A,I hava B,I hava C
I hava A,I hava B,I gut C

subn:调用格式与sub相同,只是最后返回结果中会统计替换次数。

temp=re.subn('g.t',substr,str)
print(temp)
('I hava A,I hava B,I hava C', 3)

其他

正则表达式匹配中文,英文字母和数字及_的写法!

中文标点符号的unicode编码

正则表达式(二)——Python中的相关方法的更多相关文章

  1. 正则表达式与Python中re模块的使用

    正则表达式与Python中re模块的使用 最近做了点爬虫,正则表达式使用的非常多,用Python做的话会用到re模块. 本文总结一下正则表达式与re模块的基础与使用. 另外,给大家介绍一个在线测试正则 ...

  2. 常用正则表达式与python中的re模块

    正则表达式是一种通用的字符串匹配技术,不会因为编程语言不一样而发生变化. 部分常用正则表达式规则介绍: . 匹配任意的一个字符串,除了\n * 匹配任意字符串0次或者任意次 \w 匹配字母.数字.下划 ...

  3. 【归纳】正则表达式及Python中的正则库

    正则表达式 正则表达式30分钟入门教程 runoob正则式教程 正则表达式练习题集(附答案) 元字符\b代表单词的分界处,在英文中指空格,标点符号或换行 例子:\bhi\b可以用来匹配hi这个单词,且 ...

  4. 正则表达式在python中的简单使用

    正则表达式独立与编程语言,基本上所有的编程语言都实现了正则表达式的相关操作.在Python中正则表达式的表现为re模块: import re 其操作有三个方法: my_string = "h ...

  5. js中正则表达式与Python中正则表达式的区别

    今天女票让我帮她写一个js中的正则,来提取电话号码,对于正则规则来说,js与python是基本没有区别的,重点的区别是在一些函数与方法中. python中的正则提取: import re str = ...

  6. 正则表达式与python中re模块

    一个网站,正则表达式入门的,很好 http://www.jb51.net/tools/zhengze.html 下面这个包含对python中re的介绍,也是很不错的http://www.w3cscho ...

  7. 自学Python二 Python中的屠龙刀(续)

    函数 秉承着一切皆对象的理念,函数作为对象,可以为其赋值新的对象名,也可以作为参数传递给其他函数! 正常的诸如空函数,默认参数等等我们就不提了,在这里着重提一下默认参数里面的坑和lambda函数. 当 ...

  8. 学以致用三十二-----python中函数的括号使用

    一直以来对python中函数括号的使用,有点分不清楚,到底什么时候用括号,什么时候不用括号,造成了很大看困惑. 今天来总结下. class aaa(): y = 'you' def __init__( ...

  9. 正则表达式在python中的应用

    一.常用符号 . :匹配任意字符,换行符\n除外   * :匹配前一个字符0次或无限次    ? :匹配前一个字符0次货1次 .* :贪心算法 .*? :非贪心算法 () :括号内的数据作为结果返回 ...

随机推荐

  1. Python解释器下载安装教程

    简介: 自从20世纪90年代初Python语言诞生至今,它已被逐渐广泛应用于系统管理任务的处理和Web编程.2021年10月,语言流行指数的编译器Tiobe将Python加冕为最受欢迎的编程语言,20 ...

  2. 从容器中获取宿主机IP地址

    背景: docker 中的程序需要连接外部的程序,连接的过程中会告知外部程序自己的ip地址,然后外部的程序会回连docker中的程序.由于docker使用的是rancher中的托管模式,外部程序是没办 ...

  3. 面向次世代的Windows App SDK 近况

    Project Reunion作为面向次世代Windows App Development的统一工具集.在2021年11月,第三个稳定版正式以1.0的版本号发布的同时,改名部果断出手,以全新的名称Wi ...

  4. mysql加强(6)~子查询简单介绍、子查询分类

    一.子查询简单介绍 1.什么是子查询? 一个查询之中嵌套了其他的若干查询. 在使用select 语句查询时,有时候where的查询条件中的限制条件不是一个确定的值,而是一个来自于另一个查询的结果. 子 ...

  5. AT2272 [ARC066B] Xor Sum

    我们可以知道异或可以看成不进位的加法,那么我们就可以得到 \(a + b = a\) ^ \(b + ((a \& b) << 1)\),不难发现 \(\frac{v - u}{2 ...

  6. spring学习三:Spring Bean 生命周期

    Bean 的生命周期 理解 Spring bean 的生命周期很容易.当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态.同样,当 bean 不再需要,并且从容器中移除时,可能需 ...

  7. JAVA异常与异常处理详解【转】

    感谢!!!原文地址:https://www.cnblogs.com/knightsu/p/7114914.html 一.异常简介 什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在ja ...

  8. Centos 7 下部署Django + uWSGI + Nginx

    1.废话 之前利用Django写了些测试工具,一直是直接 python manage.py runserver 8081这么来用的.用户量不大,倒也不影响什么.uWSGI+Nginx的性能肯定要好,s ...

  9. iOS应用性能调优的建议和技巧--中高级--王朋

    中级(这些是你可能在一些相对复杂情况下可能用到的) 9. 重用和延迟加载Views 10. Cache, Cache, 还是Cache! 11. 权衡渲染方法 12. 处理内存警告 13. 重用大开销 ...

  10. 解压命令tar zxvf中zxvf分别是什么意思

    x : 从 tar 包中把文件提取出来z : 表示 tar 包是被 gzip 压缩过的,所以解压时需要用 gunzip 解压v : 显示详细信息f xxx.tar.gz : 指定被处理的文件是 xxx ...