7.python之正则表达式re模块

  1. 云栖社区>
  2. 博客>
  3. 正文

7.python之正则表达式re模块

技术小胖子 2017-11-08 15:23:00 浏览813
展开阅读全文

一.正则表达式中常用元字符的复习。

通配符系列

.(点)匹配任意一个除换行符以外的字符。

*(星号)用来匹配*星号前面的字符或者一组字符0到无穷次。可以写为0

+(加号)匹配加号前面的一个字符或者一组字符1到无穷次。可以写为1

?(问号)匹配问号前面的一个字符或者一组字符0到1次。可以写为 01

{n,m}(大括号):前面的一个字符或者一组字符至少匹配n次最多匹配m次。

{n}(大括号)只匹配n次。

{n,}:至少匹配n次。


字符集系列

[abcd1234]中括号中括号在正则表达式中就是一个字符集的功能用于匹配中括号内的任意一个字符。

例1

print re.findall(r'[abcd1234]','abcdefg1234567')

输出匹配到的结果

['a', 'b', 'c', 'd', '1', '2', '3', '4']


减号或者叫横线在中括号字符集中是有特殊意义的用于指一个字符串的范围。

[a-z] : 代表一个所有的小写字母。

[0-9]代表0-9的所有数字。

[a-Z]代表所有小写和大写字母。


^(尖号)在中括号字符集中也是有特殊意义的用于字符集取反下面是例子。

^a:匹配一个不为a的任意字符。

^a-z:代表不为所有小写字母的任意字符。

 ^0-9:代表不为所有数字的任意字符。

!!注意!! .(点)  +(加号)  *(星号) ,(逗号) 这几个符号在[ ]中括号字符集中没有任何特殊意义都会被当作普通字符来处理。

-(减号)^(尖号)\(反斜杠)  这三个符号在中括号字符集中是具有特殊意义的减号则用于指定一个一个字符集的范围反斜杠依旧有转义符的作用比如d是一个普通字符\d就代表了数字0-9.

print re.findall(r'[\d]','abcdef\dg1234567')

匹配结果

['1', '2', '3', '4', '5', '6', '7']


开头和结尾

^尖号匹配以一串字符串或者一个字符串开头的字符。

$dollar匹配以一串字符串结尾或者一个字符串结尾的字符。



关于分组

()小括号用于分组。

首先来说说分组可以来实现什么功能吧

我们拿通配符加号来举个例子

加号默认情况下只能匹配加号前面的字符1次到多次。

print re.findall(r'ab+','abbbbbbcdef\dg1234567')

输出匹配结果

['abbbbbb']

前面的b被匹配了1到多次。


那么现在有一个需求就是把ab作为一组字符串ab这两个字符当作一个整体重复匹配1到多次。

这个时候就需要用到小括号来实现分组功能。

print re.findall(r'(ab)+','abbbbbbcdef\dg1234567')

输出匹配结果

['ab']

从结果可以看出ab这两个字符被当作了一个整体去匹配。

如果觉得这个例子还不够醒目不够明显可以看下面这个例子。

print re.findall(r'(ab)+haozhi','ababhaozhi')

输出匹配结果

['ab'] 

从上面这个例子说明了使用小括号分组之后被分组的表达式在findall方法中会被优先显示出来小括号内中分组的正则表达式会被显示小括号外的正则表达式也会去匹配只不过默认不显示而已.(注意只有在使用findall方法才回出现这种情况)


其实findall方法的这个特性可以理解为按照一个条件去匹配内容但是只想显示所匹配到的内容的一部分。这种功能可以使用findall这个方法结合分组特性去实现。

例如

现在需要找到“123asas456zzz765ayu”这串字符串中ayu前面的三位数。

print re.findall(r'(\d{3})ayu','123asas456zzz765ayu')    

\d 代表一个数字的字符集0-9重复匹配三次也就是说这是个三位数然后将其分组只匹配到三位数还不能满足要求后面紧跟着ayu。

输出匹配结果

['765']

这就是分组的优先级特性只显示分组中的内容。


那么如何取消这种分组的优先级特性呢

想取消find方法中的这种分组优先级特性只需要在()小括号中加上一个?: 问号和冒号这种分组优先级特性就被取消了。

print re.findall(r'(?:\d{3})ayu','123asas456zzz765ayu')

输出匹配结果

['765ayu']


竖线或管道符一般用在小括号分组中用来做一个或运算下面是个例子。

print re.findall("^www.(aaa|bbb).com$","www.bbb.com")

输出结果

['bbb']

上面这个例子没有取消分组优先的特性接下来将分组优先特性取消一下看看最原本的结果。

print re.findall("^www.(?:aaa|bbb).com$","www.bbb.com")

输出结果

['www.bbb.com']


关于\反斜杠的补充

当\反斜杠后面加上了元字符就可以去掉元字符的特殊功能使其变成一个普通的字符串。

例如

\.  \* \+ 等......

当反斜杠后面加一些普通字符后可以实现一些特殊功能。

\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:用来匹配一个特殊字符边界比如空格  逗号  &and 井号。



不常用的知识点

贪婪匹配与非贪婪匹配:

在正则中,默认遵循的就是一种贪婪匹配原则(也可以说是最大匹配,或者说尽可能的最多匹配)。

非贪婪模式就是指按照最小的范围进行匹配(尽可能的少匹配)。

这两种模式是可以切换的,请看下面的例子:

#\d匹配所有的十进制数字,+加号代表匹配一次到n次,按照正则表达式默认的匹配原则,就是贪婪匹配,加号既然最多可以匹配无限次,那么有多少数字,全部都会被匹配到。

print re.findall("\d+","as121323jh1213232321hgj12132323")

输出匹配结果:

['121323', '1213232321', '12132323']

那么如何切换到非贪婪模式匹配呢?只需要在通配符后面加上一个?问号,这个通配符就会启用惰性匹配(非贪婪匹配)

print re.findall("\d+?","as121323jh1213232321hgj12132323")

输出匹配结果:

['1', '2', '1', '3', '2', '3', '1', '2', '1', '3', '2', '3', '2', '3', '2', '1', '1', '2', '1', '3', '2', '3', '2', '3']

#+加号最小能匹配1个前面的字符或者字符串分组,非贪婪匹配就是指通配符的一个最小匹配,所以一次只匹配到了一个数字。





二.re模块的常用方法

re.findall() 用于返回一个字符串中所有能被正则表达式所匹配到的字符串以列表的方式返回。

用法re.findall(正则表达式字符串)。

s1 = "sadjhjafdsajkhjsdaysadsadduayu"

比如说想要从上面这一长串字符串中匹配出a后面有一个任一字符在紧接着一个字母u的字符串。

print re.findall('a.u',s1)

>>>['ayu']


re.finditer()作用和findall一样不过finditer返回的并不是个列表而是个迭代器对象如果需要迭代操作推荐使用finditer方法。


re.search() 在字符串中按照正则表达式去查找匹配所需要的字符串只找第一个匹配到的结果然后返回一个match对象这个对象中包含了通过正则表达式匹配的信息我们可以通过执行该对象.group方法去获取所匹配到的字符串如果找到想匹配的字符串就回返回一个None。

用法re.search(正则表达式,字符串,flag)

s1 = "hamasaki ayumi"

print re.search('a.u',s1).group()

>>>ayu

re.match()字符串中按照正则表达式去查找匹配所需要的字符串,和search不同的是match只会从字符串的开头进行匹配如果字符串开始不符合正则表达式则匹配失败

用法和search是一样的。


re.split()按照指定的正则表达式去拆分字符串。

以所有的字符串做为分隔符。

s = "a1b2c3d4e5"

print re.split(r'\d',s)

>>>['a', 'b', 'c', 'd', 'e', '']


re.sub()替换使用正则表达式匹配出字符串中的指定内容然后将其替换成指定的字符串。

s = "a1b2c3d4e5"

print re.sub(r'[a-z]','ayu',s)

>>>ayu1ayu2ayu3ayu4ayu5

re.sub()函数还有个参数可以设置替换多少次。

比如说只想替换前三个匹配到的。

s = "a1b2c3d4e5"

print re.sub(r'[a-z]','ayu',s,3)

>>>ayu1ayu2ayu3d4e5


re.subn() 和sub一样都是通过正则来替换字符串内容的功能但是subn会返回一个元组这个元组里不单单只有替换后的字符串还包含了这个字符串中的内容被替换了几次。

例如

s = "a1b2c3d4e5"

print re.subn(r'[a-z]','ayu',s)

>>>('ayu1ayu2ayu3ayu4ayu5', 5)


re.compile() 编译可以把正则表达式编译成一个正则表达式对象。可以把那些经常使用的正则表达式编译成正则表达式对象这样可以提高一定的效率。


re.match():功能和search有点像,但是最大的不同是,match只能从字符串的开头处进行匹配。


二.python正则表达式之分组(无命名和有命名分组的补充 )。

python中正则常用的分组方式大概分为两种。

方法1

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(0)

>>>010-123456

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(1)

>>>010

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(2)

>>>123456

如果正则表达式中定义了组就可以在Match对象上用group()方法提取出子串。 

注意到group(0)永远是原始字符串group(1)、group(2)……表示第1、2、……个子串。


方法2:

命名分组

print re.search(r'(?P<zone_num>^\d{3,4})-(?P<phone_num>\d{3,8})','010-123456').group("zone_num")

>>>010

print re.search(r'(?P<zone_num>^\d{3,4})-(?P<phone_num>\d{3,8})','010-123456').group("phone_num")

>>>123456




      本文转自苏浩智 51CTO博客,原文链接:http://blog.51cto.com/suhaozhi/1910537,如需转载请自行联系原作者






网友评论

登录后评论
0/500
评论