【python教程】re模块的使用方法

本文将介绍在Python语言中如何使用正则表达式。

在Python中,通过内置的re模块提供对正则表达式的支持。正则表达式会被编译成一系列的字节码,然后由通过C编写的正则表达式引擎进行执行。该引擎自从Python1.6被内置以来,近20年时间未有发生过变化,实乃我辈楷模。

简单用法

re模块支持下方语法

"."      
"^"      
"$" 
"*"     
"+"      
"?"      
*?,+?,?? 
{m,n}    
{m,n}?   
"\\"     
[]      
"|"      
(...)    
(?aiLmsux)
(?:...)  
(?P<name>...) 
(?P=name)     
# P是正则表达式,如我要提取 “我喜欢你”中的“喜欢”两个字,我可以使用正则表达式(?<=我).{2}(?=你),那么P就是?号

(?#...)  
(?=...) 
(?!...) 
(?<=...) 
(?<!...) 
(?(id/name)yes|no)

支持下面的转义或字符集

\number  
\A
\Z 
\b
\B
\d
\D       
\s
\S 
\w
\W     
\\

提供了下面的方法进行字符串的查找、替换和分割等各种处理操作。

方法 描述 返回值
compile(pattern[, flags]) 根据包含正则表达式的字符串创建模式对象 re对象
search(pattern, string[, flags]) 在字符串中查找 第一个匹配到的对象或者None
match(pattern, string[, flags]) 在字符串的开始处匹配模式 在字符串开头匹配到的对象或者None
split(pattern, string[, maxsplit=0,flags]) 根据模式的匹配项来分割字符串 分割后的字符串列表
findall(pattern, string,flags) 列出字符串中模式的所有匹配项 所有匹配到的字符串列表
sub(pat,repl, string[,count=0,flags]) 将字符串中所有的pat的匹配项用repl替换 完成替换后的新字符串
finditer(pattern, string,flags) 将所有匹配到的项生成一个迭代器 所有匹配到的字符串组合成的迭代器
subn(pat,repl, string[,count=0,flags]) 在替换字符串后,同时报告替换的次数 完成替换后的新字符串及替换次数
escape(string) 将字符串中所有特殊正则表达式字符串转义 转义后的字符串
purge(pattern) 清空正则表达式  
template(pattern[,flags]) 编译一个匹配模板 模式对象
fullmatch(pattern, string[, flags]) match方法的全字符串匹配版本 类似match的返回值

同时还定义了下面几种匹配模式,单个大写字母是缩写,单词是完整模式名称,引用方法为re.A或者re.ASCII,两者都可以,注意全部是大写:

A  :ASCII       
I  :IGNORECASE  
L  :LOCALE      
M  :MULTILINE  
S  :DOTALL      
X  :VERBOSE    
U  :UNICODE

反斜杠的困扰:\

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

一、compile(pattern, flags=0)

这个方法是re模块的工厂方法,用于将字符串形式的正则表达式编译为Pattern模式对象,可以实现更高效率的匹配。第二个参数flag是匹配模式。

使用compile()完成一次转换后,再次使用该匹配模式的时候就不用进行转换了。经过compile()转换的正则表达式对象也能使用普通的re方法。其用法如下:

import re

pat = re.compile(r'abc')

print(pat.match("abc123"))

d2b5ca33bd123339

import re

pat = re.compile(r'abc')

print(pat.match("abc123").group())

d2b5ca33bd123548

 

经过compile()方法编译过后的返回值是个re对象,它可以调用match()、search()、findall()等其他方法,但其他方法不能调用compile()方法。实际上,match()和search()等方法在使用前,Python内部帮你进行了compile的步骤。

d2b5ca33bd123718

那么是使用compile()还是直接使用re.match()呢?看场景!如果你只是简单的匹配一下后就不用了,那么re.match()这种简便的调用方式无疑来得更简单快捷。如果你有个模式需要进行大量次数的匹配,那么先compile编译一下再匹配的方式,效率会高很多。

以下的内容,都采用直接通过re模块调用方法的形式。

二、match(pattern, string, flags=0)

match()方法会在给定字符串的开头进行匹配,如果匹配不成功则返回None,匹配成功返回一个匹配对象,这个对象有个group()方法,可以将匹配到的字符串给出。

d2b5ca33bd124005

import re

ret = re.match(r"abc","abc123")

print(ret.group())

d2b5ca33bd124408

 

三、search(pattern, string, flags=0)

 

在文本内查找,返回第一个匹配到的字符串。它的返回值类型和使用方法与match()是一样的,唯一的区别就是查找的位置不用固定在文本的开头。

import re

obj = re.search(r"abc","123abc456abc789")

print(obj)

d2b5ca33bd124559

import re

obj = re.search(r"abc","123abc456abc789").group()

print(obj)

d2b5ca33bd124708

 

四、findall(pattern, string, flags=0)

 

作为re模块的三大搜索函数之一,findall()和match()、search()的不同之处在于,前两者都是单值匹配,找到一个就忽略后面,直接返回不再查找了。而findall是全文查找,它的返回值是一个匹配到的字符串的列表。这个列表没有group()方法,没有start、end、span,更不是一个匹配对象,仅仅是个列表!如果一项都没有匹配到那么返回一个空列表。

import re

obj = re.findall(r"abc","123abc456abc789")

print(obj)

d2b5ca33bd124835

d2b5ca33bd125127

五、split(pattern, string, maxsplit=0, flags=0)

 

re模块的split()方法和字符串的split()方法很相似,都是利用特定的字符去分割字符串。但是re模块的split()可以使用正则表达式,因此更灵活,更强大,而且还有“杀手锏”。看下面这个例子,匹配模式是加减乘除四个运算符中的任何一种,通过split()将字符串分割成一个一个的数字:

>>> s = "8+7*5+6/3"
>>> import re
>>> a_list = re.split(r"[\+\-\*\/]",s)
>>> a_list
['8', '7', '5', '6', '3']
split有个参数maxsplit,用于指定分割的次数:

>>> a_list = re.split(r"[\+\-\*\/]",s,maxsplit= 2)
>>> a_list
['8', '7', '5+6/3']

利用分组的概念,re.split()方法还可以保存被匹配到的分隔符,这个功能非常重要!为什么呢?比如,你要计算8+7,是不是要同时获得8,+,7三个字符?就如同下面的例子,字符串s = “8+7*5+6/3″,想要计算字符串内的表达式的值,你必须获得其中加减乘除的符号。

>>> a_list = re.split(r“([\+\-\*\/])”,s) # 注意这里添加了括号!
>>> a_list
['8', '+', '7', '*', '5', '+', '6', '/', '3']

六、sub(pattern, repl, string, count=0, flags=0)

sub()方法类似字符串的replace()方法,用指定的内容替换匹配到的字符,可以指定替换次数。

>>> s = "i am jack! i am nine years old ! i like swiming!"
>>> import re
>>> s = re.sub(r"i","I",s)
>>> s
'I am jack! I am nIne years old ! I lIke swImIng!'
sub()方法有一个高级功能——“分组引用”,这是一个非常强大的功能,运用好了能发挥巨大的作用!举例如下:
import re

origin = "Hello,world!"
r = re.sub(r“(world)”, r“<em>\1<em>”, origin) # 注意括号和\1的作用!
print(r)
运行结果:
Hello,<em>world<em>!

其实现机制是首先在正则表达式里用括号建立了一个分组,然后在要替换进去的字符串里用“\1”引用了这个分组匹配到的内容。PS:还记得正则语法里反向引用的知识点吗?

 

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容