前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python re模块

python re模块

作者头像
py3study
发布2018-08-02 16:06:06
5410
发布2018-08-02 16:06:06
举报
文章被收录于专栏:python3

正则表达式(可以称为REs,regex,regex pattens)是一个小巧的,高度专业化的编程语言,它内嵌于python开发语言中,可通过re模块使用。正则表达式的pattern可以被编译成一系列的字节码,然后用C编写的引擎执行。

常用正则表达式符号,基本上,包含了90%的场景。

'.'

默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行

'^'

匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)

'$'

匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以

'*'

匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']

'+'

匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']

'?'

匹配前一个字符1次或0次

'{m}'

匹配前一个字符m次

'{n,m}'

匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']

'|'

匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'

'(...)'

分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c

'\A'

只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的

'\Z'

匹配字符结尾,同$

'\d'

匹配数字0-9

'\D'

匹配非数字

'\w'

匹配[A-Za-z0-9]

'\W'

匹配非[A-Za-z0-9]

's'

匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'

'(?P<name>...)'

分组匹配

最常用的匹配语法

代码语言:javascript
复制
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splita 以匹配到的字符当做列表分隔符
re.sub      匹配字符并替换

反斜杠的困扰 与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

举个列子:

匹配以Chen开头的字符串

代码语言:javascript
复制
import re
result = re.match("^Chen","ChenLong")
print(result)

执行输出

_sre.SRE_Match object; span=(0, 4), match='Chen'

结果是一个匹配对象,请注意结尾的match='Chen' 表示匹配出了Chen

如果没有匹配上,结果为None

打印匹配结果,使用group()方法查看

代码语言:javascript
复制
print(result.group())

执行输出 Chen

注意:如果没有匹配上,使用group()会报错。

上面的正则匹配规写死了,比如^Chen 这种需求,用in方法就可以实现了。

下面说一个简单的例子

匹配以Chen开头的以及后面的数字

代码语言:javascript
复制
import re
result = re.match("^Chen\d","Chen356Long")
print(result.group())

执行输出

Chen3

注意:

\d 表示匹配一个数字

如果想要匹配多个数字,使用\d+

代码语言:javascript
复制
import re
result = re.match("^Chen\d+","Chen356Long")
print(result.group())

执行输出

Chen356

匹配任意字符.+

代码语言:javascript
复制
res = re.match(".+","Chen321Long123")
print(res.group())

执行输出

Chen321Long123

匹配单个字符.

代码语言:javascript
复制
res = re.match(".","Chen321Long123")
print(res.group())

执行输出: C

匹配Long

代码语言:javascript
复制
res = re.match("^L.+g","Chen321Long123")
print(res)

执行输出: None

为什么呢?因为match是从左至右匹配,由于Long在字符串的中间,写任何正则都无法匹配出Long。

需要用到另外一个方法search,表示从整个文本中去搜索。结果只会返回一次,如果有多个结果,会返回第一个结果。

代码语言:javascript
复制
res = re.search("L.+g","Chen321Long123")
print(res.group())

执行输出: Long

如果使用L.+g$ 是匹配不到Long的,为什么呢?

$表示匹配整个字符串的结尾,而结尾是3。由于123不是我想要的,所以不能写g$

由于.+是匹配任意字符,如果只想匹配字母呢?使用[a-z]

代码语言:javascript
复制
res = re.search("L[a-z]+g","Chen321Long123")

匹配所有字母大小写呢?使用[a-zA-Z]

代码语言:javascript
复制
res = re.search("L[a-zA-Z]+g","Chen321Long123")

匹配jack

代码语言:javascript
复制
res = re.search("[a-z]+k","123#tom#jack#rose")
print(res)

执行输出:

_sre.SRE_Match object; span=(8, 12), match='jack'

'?' 匹配前一个字符1次或0次

匹配字母a

代码语言:javascript
复制
res = re.search("a?","alin")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 1), match='a'

匹配字母a

代码语言:javascript
复制
res = re.search("a?","lina")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 0), match=''

结果显示没有匹配上,请注意,? 可以匹配0次,也就是不匹配的情况。所以它的结果不是None

'?' 匹配前一个字符1次或0次

匹配aa或者aaa

代码语言:javascript
复制
res = re.search("aaa?","aalinaaa")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 2), match='aa'

请注意aaa? 需要拆分一下aa和aaa? 为什么呢? '?'是匹配0次或者1次数

aaa?匹配0次就是aa,匹配1次,就是aaa?

'{m}' 匹配前一个字符m次

匹配3个数字

代码语言:javascript
复制
res = re.search("[0-9]{3}","aa1x2a345aa")
print(res)

执行输出:

_sre.SRE_Match object; span=(6, 9), match='345'

匹配1到3次

代码语言:javascript
复制
res = re.search("[0-9]{1,3}","aa1x2a345aa")
print(res)

执行输出:

_sre.SRE_Match object; span=(2, 3), match='1'

匹配所有数字

代码语言:javascript
复制
res = re.search("[0-9]+","aa1x2a345aa")
print(res)

执行输出:

_sre.SRE_Match object; span=(2, 3), match='1'

为什么只有一个1呢?因为search只会返回一个结果,后续的不再返回。这个时候,需要用到findall方法

注意:findall没有group()方法

代码语言:javascript
复制
res = re.findall("[0-9]+","aa1x2a345aa")
print(res)

执行输出:

['1', '2', '345']

所有的数字,都匹配出来了。

只匹配第3次的结果

代码语言:javascript
复制
res = re.findall("[0-9]{3}","aa1x2a345aa")
print(res)

执行输出:

['345']

'|' 匹配|左或|右的字符

匹配abc或者ABC

代码语言:javascript
复制
res = re.findall("abc|ABC","ABCBabcCD")
print(res)

执行输出:

['ABC', 'abc']

'(...)'分组匹配

匹配abc,在匹配c 2次

代码语言:javascript
复制
res = re.search("abc{2}","xiabccc")
print(res)

执行输出:

_sre.SRE_Match object; span=(2, 6), match='abcc'

复杂的例子

匹配abc 2次,匹配||= 2次。注意:\| 转义了,表示|

代码语言:javascript
复制
res = re.search("(abc){2}(\|\|=){2}","abcabc||=||=")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 12), match='abcabc||=||='

'\A'只从字符开头匹配

'\Z'匹配字符结尾,同$

'\A' 效果和'^' 是一样的。

匹配以数字开头,字母结尾

代码语言:javascript
复制
res = re.search("\A[0-9]+[a-z]\Z","123a")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 4), match='123a'

'\d' 匹配数字

代码语言:javascript
复制
res = re.search("\A\d+[a-z]\Z","123a")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 4), match='123a'

'\D' 匹配非数字

匹配非数字

代码语言:javascript
复制
res = re.search("\D+","123a$ -\n")
print(res)

执行输出:

_sre.SRE_Match object; span=(3, 8), match='a$ -\n'

'\w'匹配[A-Za-z0-9]

代码语言:javascript
复制
res = re.search("\w+","1dF23$- \r\na")
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 5), match='1dF23'

'\W'匹配非[A-Za-z0-9]

代码语言:javascript
复制
res = re.search("\W+","1dF23$- \r\na")
print(res)

执行输出:

_sre.SRE_Match object; span=(5, 10), match='$- \r\n'

's'匹配空白字符、\t、\n、\r

代码语言:javascript
复制
res = re.search("\s+","1dF23$- \r\na")
print(res)

执行输出:

_sre.SRE_Match object; span=(7, 10), match=' \r\n'

'(?P<name>...)' 分组匹配 

组名为id,匹配数字

代码语言:javascript
复制
res = re.search("(?P<id>[0-9]+)","abcd1234daf@34")
#使用groupdict()方法打印组名
print(res.groupdict())

执行输出:

{'id': '1234'}

再添加一个分组name,匹配字母大小写

代码语言:javascript
复制
res = re.search("(?P<id>[0-9]+)(?P<name>[a-zA-Z]+)","abcd1234daf@34")
print(res.groupdict())

执行输出:

{'name': 'daf', 'id': '1234'}

返回的结果是一个字典,如果想取值的话,使用如下方法:

代码语言:javascript
复制
res = re.search("(?P<id>[0-9]+)(?P<name>[a-zA-Z]+)","abcd1234daf@34")
print(res.groupdict())
#第一种方法,直接传值
print(res.group("id"))
#第二种方法,用字典的方式
print(res.groupdict()['name'])

执行输出:

{'id': '1234', 'name': 'daf'}

1234

daf

举个复杂的例子

身份证号,前2位是省,再后面2位是市,再后面2位是区,再后面8位是出生日期

代码语言:javascript
复制
res = re.search("(?P<province>[0-9]{2})(?P<city>[0-9]{2})(?P<area>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
print(res)

执行输出:

{'birthday': '1993', 'city': '14', 'province': '37', 'area': '81'}

re.split 以匹配到的字符当做列表分隔符

代码语言:javascript
复制
res = re.split("[0-9]","abc12de3f45GH")
print(res)

执行输出:

['abc', 'de', 'f', 'GH']

re.sub   匹配字符并替换

代码语言:javascript
复制
res = re.sub("[0-9]+","|","abc12de3f45GH")
print(res)

执行输出:

abc|de|f|GH

只替换一个

代码语言:javascript
复制
res = re.sub("[0-9]+","|","abc12de3f45GH",count=1)
print(res)

执行输出:

abc|de3f45GH

仅需轻轻知道的几个匹配模式

代码语言:javascript
复制
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上面)
S(DOTALL): 点任意匹配模式,改变'.'的行为

忽略大小写

代码语言:javascript
复制
res = re.search("[a-z]+","abcA",flags=re.I)
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 4), match='abcA'

代码语言:javascript
复制
res = re.search(r"^a","\nabc\neee",flags=re.M)
print(res)

执行输出:

_sre.SRE_Match object; span=(1, 2), match='a'

匹配任意字符

代码语言:javascript
复制
res = re.search(r".+","\nabc\neee",flags=re.S)
print(res)

执行输出:

_sre.SRE_Match object; span=(0, 8), match='\nabc\neee'

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/03/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档