1、引言
Python通过标准库的re模块支持正则表达式。
Python中完成模式匹配的主要方法:搜索和匹配。
搜索,即在字符串任意部分中搜索匹配的模式,而匹配是指,判断一个字符串能否从起始处全部或部分的匹配某个模式。搜索通过search()函数或方法来实现,匹配通过match()函数或方法来实现。
2、正则表达式使用的特殊符号和字符
- literal 匹配字符串的值
- re1|re2 匹配正则表达式re1或re2
- . 匹配任意字符(换行符除外)
- ^ 匹配字符串的开始
- $ 匹配字符串的结尾
- * 匹配前面出现的正则表达式零次或多次
- +匹配前面出现的正则表达式一次或多次
- ?匹配前面出现的正则表达式零次或一次
- {N} 匹配前面出现的正则表达式N次
- {M,N} 匹配重复出现M次到N次的正则表达式
- […] 匹配字符组里出现的任意一个字符
- […x-y…] 匹配从字符x到y中的任意一个字符
- [^…] 不匹配此字符集中出现的任意一个字符
- (*|+|?|{})? 用于上面出现的任何“非贪婪”。版本重复匹配次数符号。如.*?a表示匹配到第一个a出现取前面任意长度的字符。
- (…) 匹配封闭括号中正则表达式(RE),并保存为子组
- \d 匹配任何数字,和[0-9]一样(\D是\d的反义:任何非数字)
- \w 匹配任何数字字母字符,和[A-Za-z0-9_]相同(\W是\w的反义)
- \s 匹配任何空白符,和[\n\t\r\v\f]相同(\S是\s的反义)
- \b 匹配单词边界(\B是\b的反义)
- \nn 匹配已保存的子组(参考(…))如price:\16
- \c 逐一匹配特殊字符c(即,取消它的特殊含义,按字面匹配)
- \A(\Z)匹配字符串的起始(结束)
(1)用管道符号(|)匹配多个正则表达式
(2)匹配除换行符外任意一个单个的字符(.)
(3)从字符串的开头或结尾或单词边界开始匹配(^ $或\A \Z \b \B)
(4)创建字符类([])
(5)指定范围(-)和否定(^)
(6)使用闭包操作符(* + ? {})实现多次出现/重复匹配
?的两种含义:
- 表示匹配出现0或1次;
- 紧跟在表示重复的元字符后面时(如+?),表示要求搜索引擎匹配的字符串越短越好。(*+?{m,n})尽量“吸收”更多的字符,这叫“贪心”。
(7)特殊字符表示、字符集
- \d表示十进制数字(\D表示非十进制数字)
- \w表示整个字符数字的字符集(\W)
- \s表示空白字符(\S)
(8)用圆括号(())组建组
()的功能:对正则表达式进行分组;匹配子组。
对正则表达式进行分组可以实现用不同的正则表达式去匹配字符串,或重复整个正则表达式多次。
使用子组匹配是为了能够提取匹配模式的内容,Python的re支持此功能。
3、正则表达式和Python语言
re模块
1.5中被引入,在1.6重写,改进性能且添加了对Unicode的支持,但接口没有变。
re模块支持功能更强大,更通用的Perl风格的正则表达式,允许多线程共享同一经过编译的正则表达式对象,同时还支持对正则表达式分组进行命名和按名字调用。
reconvert模块
regex/regsub模块存在于Python早期版本中,在2.5中已被移除,reconvert模块帮助开发者从regex/regsub模块迁移到re模块。
re引擎在1.6被重写,改进了性能并添加了对unicode的支持。
(1)re模块的核心函数和方法
①模块的函数
- compile(pattern,flags=0) 对正则表达式模式pattern进行编译,并返回一个regex对象,flags是可选标识符
②re模块的函数和regex对象的方法
- match(pattern,string,flags=0) 使用正则表达式模式pattern匹配字符串string,匹配成功返回匹配对象,失败返回None,flags是可选标识符
- search(pattern,string,flags=0) 在字符串string中搜索正则表达式模式pattern的第一次出现,匹配成功返回匹配对象,失败返回None,flags是可选标识符
- findall(pattern,string[,flags]) 在字符串string中搜索正则表达式模式pattern的所有非重复出现,返回一个匹配对象的列表
- finditer(pattern,string[,flags]) 和findall()相同,只是返回的不是列表而是迭代器
- split(pattern,string,max=0) 根据pattern中的分隔符把字符串string分割为一个列表,最多分割max次,默认分割所有匹配的地方
- sub(pattern,repl,string,max=0) 把string中所有匹配pattern的地方替换成字符串repl,最多替换max次,默认替换所有匹配的地方
③匹配对象的方法
- group(num=0) 返回全部匹配对象(或指定编号是num的子组)
- groups()返回包含全部匹配的子组的元组(若匹配不成功,就返回一个空元组)
(2)使用compile()编译正则表达式
大多数re模块函数都可以作为regex对象的方法。用compile()预编译正则表达式可以提升性能。
(3)匹配对象和group()、groups()方法
在match()或search()被成功调用之后所返回的对象类型–匹配对象。
匹配对象有两个主要的方法:group()和groups()。
group()方法或者返回所有匹配对象或是根据要求返回某个特定子组。groups()返回一个包含唯一或所有子组的元组。
如果正则表达式中没有子组,groups()返回一个空元组,而group()仍会返回全部匹配对象。
(4)用match()匹配字符串
re模块的match()函数、正则表达式对象(regex对象)的match()方法
>>>m=re.match('foo','foo')
>>>if m is not None:
m.group()
(5)search()在一个字符串中查找一个模式(搜索与匹配的比较)
>>>m=re.match('foo','seafood')
>>>if m is not None: #匹配失败
m.group()
>>>m=re.search('foo','seafood')
>>>if m is not None: #匹配成功
m.group()
(6)匹配多个字符串(|)
>>>bt='bat|bet|bit'
>>>m=re.match(bt,'bat')
(7)匹配任意单个字符(.)
(.)不能匹配换行符或非字符(即空字符串)
>>>anyend='.end'
>>>m=re.match(anyend,'end')
>>>if m is not None:m.group()
... #没有字符匹配,匹配失败
(8)创建字符集合([])
(9)重复、特殊字符和子组
>>>m=re.match('(a(b))','ab')
>>>m.group()#所有匹配部分
'ab'
>>>m.group(1)匹配的子组1
'ab'
>>>m.group(2)匹配的子组2
'b'
>>>m.groups()所有匹配的子组的元组
('ab','b')
(10)从字符串开头或结尾匹配以及在单词边界上的匹配
(11)用findall()找到每个出现的匹配部分(1.5.2)
findall()用于非重叠地搜索某字符串中一个正则表达式模式出现的情况。
类似于search()执行字符串搜索,findall()总返回一个列表,若未找到匹配,返回空列表。findall()用于包含子组的搜索时,会返回一个元组的列表。
(12)用sub()(和subn())进行搜索和替换
subn()和sub()一样,都是将字符串中所有匹配正则表达式模式的部分进行替换,只是subn()返回一个表示替换次数的数字,替换后的字符串和替换次数作为一个元组被返回。
(13)用split()分割(分割模式)
re模块和正则表达式对象的方法split()与字符串的split()方法相似,前者根据正则表达式模式进行分割,后者根据固定的字符串分割,前者较后者,显著提升了字符分割的能力。
4、常用正则表达式汇总
(1)校验数字
数字:^\d*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9]\d*)+(\.\d{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+\.\d{1,2}$
正数、负数、和小数:^(\-)?\d+(\.\d+)?$
有两位小数的正实数:^\d+\.\d{2}$
有1~3位小数的正实数:^\d+\.\d{1,3}$
非零的正整数:^[1-9]\d*$
非零的负整数:^-[1-9]\d*$
(2)校验字符的表达式
汉字:^[\u4e00-\u9fa5]+$
英文和数字:^[A-Za-z0-9]+$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$
(3)特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
国内手机号码:^1[34578]{1}\d{9}
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z]\w{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
IP地址:^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$