文章目录
前言
在学习完Python基础知识后,开始学习正则表达式。
一、正则表达式概念
- 正则表达式(regular expression,Re),是用来简洁表达一组字符串的表达式。它是一种通用的字符串表达框架。
- 在文本处理中的应用:
(1) 表达文本类型的特征(病毒、入侵);
(2) 同时查找或替换一组字符串;
(3) 匹配字符串的全部或部分(主要); - 正则表达式的使用:
(1) 编译:将符合正则表达式语法的字符串转换成正则表达式特征;
编译之前的正则表达式只是一个符合正则表达式语法的单一字符串;
编译后的特征与一组字符串是对应的
二、正则表达式的语法
正则表达式语法由字符串和操作符组成。
2.1 常用的操作符
(1) .(点):表示任何单个字符,可以代表字符表上所有出现的一个字符;
(2) [] (方括号):是一个字符集,它对单个字符给出取指范围,[abc]表示a,b和c,[a-z]表示a-z的单个字符,[^abc]表示一个字符既不是a也不是b也不是c;
(3) *(星号):表示星号之前的字符出现0次或无限次扩展;
(4) +(加号):表示加号之前的字符出现1次或无限次扩展;
(5) ?(问号):表示问号之前的字符出现0次或1次扩展;
(6) |(竖线):表示左右表达式任选其一;abc|def表示abc或者def字符串;
(7) {m}:表示扩展前一个字符m次;如ab{2}c表示abbc;
(8) {m,n}:表示扩展前一个字符m至n次(包含n次);ab{1,2}c表示abc,abbc;
(9) ^(异或符号):异或符号如果没有出现在方括号中,表示匹配字符串的开头;^abc表示以abc为开头的字符串;
(10) $:匹配字符串的结尾;abc$表示以abc为结尾的字符串;
(11) ():是分组标记,在括号内部只能使用或操作符(|),(abc)表示abc,(abc|def)表示abc或者def;
(12) \d:表示数字,等价于[0-9];
(13) \w:表示单词字符,等价于[A-Za-z0-9_];
2.2 经典正则表达式实例
(1) ^[A-Za-z]+$:由26个字母组成的字符串;
(2) ^[A-Za-z0-9]+$:由26个字母和数字组成的字符串;
(3) ^-?\d+$:整数形式的字符串;
(4) ^[0-9]*[1-9][0-9]*$:正整数形式的字符串;
(5) [1-9]\d{5}:中国境内邮政编码;
(6) [\u4e00-\u9fa5]:用UTF-8编码约定了中文字符的取值范围;
(7) \d{3}-\d{8}|\d{4}-\d(7):表示国内电话号码;
(8)匹配IP地址的正则表达式,IP地址分四段,每段0-255;0-99可以表示为[1-9]?\d,100-199可以用1\d{2}表示,200-249可以用2[0-4]\d表示,250-259可以用25[0-5]表示,因此IP地址的正则表达式可以表示为(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])
三、Re库的基本使用
Re库是Python的标准库,主要用于字符串匹配;通过import re来调用这个库。re库使用原生字符串类型表示正则表达式。
3.1 正则表达式的表示类型
(1) 原生字符串类型(raw string类型):指不包含转义符的字符串,在字符串前加一个小写的r;
(2) 字符串类型:比较繁琐,且它会将\理解为转义符,所以\d表示数字则需要变为\d来表示,也就是说原本出现\的地方都需要再增加一个斜杠来表示。
3.2 Re库主要功能函数
(1) re.search(pattern,string,flags=0):用于在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象;也就是搜索和正则表达式一样的地方;
pattern:正则表达式的字符串或原生字符串表示;
string:待匹配的字符串;
flags:正则表达式使用时的控制标记;
通过正则表达式来匹配一个string,同时用一些标记来控制这样的查找,这样的常用标记有三个,
re.I表示re.IGNORECASE,那么它在匹配正则表达式的时候会忽略大小写,比如[A-Z]既可以匹配到大写的字母也可以匹配到小写的字母;
re.M表示re.MULTILINE,它能够操作或作用于正则表达式中的异或操作符,由于异或操作符是匹配字符串开头,当使用re.M就会匹配每行的字符串开头部分;
re.S/re.DOTALL表示对点操作符进行作用,能够让点匹配所有的字符;由于默认的re库中可以匹配除了换行符之外的所有字符,当使用re.S后就可以匹配所有字符包括换行符。
import re
match=re.search(r'[1-9]\d{5}','BIT 100081')
if match:
print(match.group(0))
打印出100081
(2) re.match(pattern,string,flags=0):指从一个字符串的开始位置起,匹配正则表达式,返回match对象;它只在给定字符串的开始位置起匹配正则表达式;参数与search函数相同。
import re
match=re.match(r'[1-9]\d{5}','BUT 100081')
if match:
match.group(0)
//回车之后无输出
match.group(0)//直接调用报错,显示nanotype,表示match为空
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
match.group(0)
AttributeError: 'NoneType' object has no attribute 'group'
由于给的字符串起始并不是邮政编码,所以会返回空变量,故调取group方法报错,所以如果希望对匹配的结果进行使用,一定要加if语句判断这个match是不是空的,要把空的情况排除掉,不能用空的函数取调用后面的方法,否则系统会报错。
import re
match=re.match(r'[1-9]\d{5}','100081 BIT')//调整参数后得到期望输出
if match:
match.group(0)
'100081'//返回结果
(3) re.findall(pattern,string,flags=0):搜索字符串,并能够以列表的类型返回全部能够匹配的字符串;它能够在给定字符串中搜素所以与正则表达式相同的字符串的子串;
import re
ls=re.findall(r'[1-9]\d{5}','BIT100081 TSU100084')
ls
['100081', '100084']//返回结果
(4) re.split(pattern,string,maxsplit=0,flags=0):能够将一个字符串按照正则表达式匹配的结果进行分割,分割之后返回字串的列表类型;
其中新出现的maxsplit参数表示最大分割数,超过最大分割数的部分可以作为一个整体最后输出出来。
从下面代码可以看到,split函数是将匹配的部分去掉,去掉的部分作为分割的字符串元素放到一个列表里
import re
re.split(r'[1-9]\d{5}','BIT100081 TSU100084')
['BIT', ' TSU', '']//返回结果
当增加maxsplit=1后,可以看出在整个字符串中只匹配了第一个位置,匹配之后将BIT分割出来,成为一个部分,剩下的所有部分作为一个完整字符串不再进行正则表达式的匹配,作为列表的最后一个变量输出出来。
import re
re.split(r'[1-9]\d{5}','BIT100081 TSU100084',maxsplit=1)
['BIT', ' TSU100084']//返回结果
(5) re.finditer(pattern,string,flags=0):能够搜素字符串,返回一个匹配结果的迭代类型,每个迭代对象是一个match对象,因此它可以通过循环方式对每一个匹配进行相关操作;
import re
for m in re.finditer(r'[1-9]\d{5}','BIT100081 TSU1000841'):
if m:
print(m.group(0))
100081//返回结果
100084
(6) re.sub(pattern,repl,string,count=0,flags=0):能在一个字符串中替换所有匹配正则表达式的子串,返回替代后的字符串;
其中repl表示当pattern匹配到某一个字符串后,替换的那个字符串;
count表示匹配的最大次数;
import re
re.sub(r'[1-9]\d{5}',':zipcode','BIT100081 TSY100084')
'BIT:zipcode TSY:zipcode//返回结果
上述的re.search()等是Re库的函数式用法,如果采用面向对象用法,则为
pat=re.compile(r'[0-9]\d{5}')
rst=pat.search('BIT 100081')
经过一次编译,需要多次对正则表达式进行使用和匹配时,就可以用这种方式加快整个程序的运行。
regex=re.compile(pattern,flags=0)可以将正则表达式的字符串形式编译成正则表达式对象,注意原生字符串不是正则表达式,regex才是正则表达式,它代表了一组字符串,那么当变成regex.<函数>形式时,里面正则表达式的参数需要去掉,直接给出需要匹配的字符串就可以。
四、Re库的match对象
match对象包含了一次正则表达式匹配过程中出现的更多的信息
match=re.search(r'[1-9]\d{5}','BIT 100081')//search函数结果用match保存
if match://用if语句看match是不是成立
print(match.group(0))
100081//返回对象
type(match)//用type检查match的类型
<class 're.Match'>//返回的是re.Match类型
4.1 Match对象的属性
(1) .string表示match匹配结果所对应的待匹配的文本;
(2) .re是匹配时使用的pattern对象,这个pattern对象就是正则表达式;
(3) .pos表示匹配正则表达式文本的开始位置;
(4) .endpos表示搜索正则表达式文本的结束位置;
4.2 Match对象的方法
(1) .group(0)方法获得匹配后的字符串;
(2) .start方法匹配字符串在原始字符串中的开始位置;
(3) .end表示匹配字符串在原始字符串的结束位置;
(4) .span返回一个元组类型,包括**(.start(), .end())**。
import re
m=re.search(r'[1-9]\d{5}','BIT100081 TSU1000841')
m.string
'BIT100081 TSU1000841'//返回对象,待匹配字符串
m.re
re.compile('[1-9]\\d{5}')//表示程序内部认为只有经过compile之后的正则表达式才是一个正则表达式,没有经过compile的只是正则表达式的一种表示
m.pos
0
m.endpos
20//由此可以看到search函数是对字符串的0-20的位置开始搜索的
m.group(0)
'100081'//返回匹配结果,match对象返回的是第一次匹配的对象,如果希望返回每一次的返回对象,需要用finditer()函数来实现
m.start()
3//匹配的起始位置
m.end()
9//匹配的结尾位置
m.span()
(3, 9)//起始和结尾位置的元组类型
五、Re库的贪婪匹配和最小匹配
Re库默认采用贪婪匹配,即输出匹配最长的子串;但是也可以通过如下操作符获得最小匹配(通过在操作符后添加问号)
(1) *?表示前一个字符0次或无限次拓展,但是是最小匹配;
(2) +?表示前一个字符1次或无限次拓展,但是是最小匹配;
(3) ??表示前一个字符0次或1次拓展,但是是最小匹配;
(4) {m,n}?表示前一个字符拓展m到n次拓展(含n次),但是是最小匹配;
总结
主要学习了Re(正则表达式)库入门,其在文本操作中用途广泛,后续用起来。