码迷,mamicode.com
首页 > 其他好文 > 详细

re模块

时间:2019-01-11 18:09:49      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:amp   match   特殊字符   查找   十进制   范围   概念   pil   换行符   

正则表达式并不是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(rI\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(rc\\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模块

标签:amp   match   特殊字符   查找   十进制   范围   概念   pil   换行符   

原文地址:https://www.cnblogs.com/xulan0922/p/10242276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!