在Python里面,处理字符串除了基本的split,格式化操做等等,还可使用正则表达式。使用正则表达式,须要导入模块re。正则自己也是一门语言,像下围棋同样,入门很容易,不过要玩的很溜就得花时间了。html
老实说,老男孩13期的正则表达式的视频真的很烂,那个讲课的估计是个新人,说话颠三倒四,逻辑混乱,豆子听完仍是稀里糊涂。python
课后在网上找到一篇强文正则表达式
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.htmlapp
拜读以后,受益不浅。ide
基本规则以下所示:函数
re模块有下面几个经常使用的函数spa
1. findall(pattern, string, flags=0),这个函数会返回一个列表,列表的元素是匹配到的字符串orm
例1,下面会匹配出以a开头的全部单词,\w+表示一个或者多个字母数字或者下划线,由于不包括空格,因此至关于单个的单词了视频
>>> import re ret=re.findall('a\w+','abc aaa bbh kjk hkk add') print(ret) ['abc', 'aaa', 'add']
例2,在字符集里面的元素能够表示或的意义。字符集里面特殊的字符会失去意义;可是他自己有2个特殊的字符,-表示范围,^表示取反,好比说我须要查找加减乘除的符号,那么-由于有特殊含义,所以须要用转移符\转义htm
>>> import re a=re.findall('[+\-*/]\d','3+3-2*4/2') print(a) ['+3', '-2', '*4', '/2']
2. search(pattern,string,flags)会经过pattern去匹配,若是匹配成功,会返回一个match对象,不然返回None。而后能够经过group()函数获取对象里面的字符串
例3
>>> import re obj = re.search('\d+', '123uuasf') if obj: print(obj.group()) ------------- 123
3. match(pattern,string,flags)会经过pattern去匹配,若是匹配成功,会返回一个match对象,不然返回None。而后能够经过group()函数获取对象里面的字符串。他和search的区别在于match只能匹配字符串开头的字符,后面的没法匹配;而search能够匹配到任意位置的字符串。
例4
import re obj = re.match('\d+', 'u123uu888asf') if obj: print(obj.group()) ------------- 123
4.finditer(pattern,string,flags) 搜索string,返回一个顺序访问每个匹配结果(Match对象)的迭代器。
例5,我但愿匹配一个括号内的四则运算
注意他们的区别,search和match都返回了match对象,而后能够经过group获取字符串;而findall返回的是列表,由于我使用了圆括号分组,所以他会返回圆括号里面的内容;如何获取全部的内容呢,能够经过 finditer,他至关于一个增强版的search,会找到全部match对象放入一个列表,咱们能够循环这个列表而后获取每一个元素的group内容。
>>> a=re.match('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))') print(a.group()) print('search'.center(40,'-')) a=re.search('\(([+\-*/]?\d+\.?\d*){1,}\)','2-(3*(2.2-3*3))') print(a.group()) print('findall'.center(40,'-')) a=re.findall('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))') for item in a: print(item) print('finditer'.center(40,'-')) a=re.finditer('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))') for item in a: print(item.group()) ------------------------------------------- (-3.2) -----------------search----------------- (2.2-3*3) ----------------findall----------------- -3.2 *3 ----------------finditer---------------- (-3.2) (22-3*3)
5.sub(pattern, repl, string, count=0, flags=0)
用于替换匹配的字符串
例6 替换2次
>>> ss='one,two,three' print(re.sub('\w+','AAA',ss,2)) AAA,AAA,three
6.split(pattern, string, maxsplit=0, flags=0)
>>> a='i am ha happy man' print(re.split('am',a)) ----------------- ['i ', ' ha happy man']
除了上面的基本使用以外,还有几点须要注意。
*转移符\的使用,Python自己有转移符,在Re模块中也有转移符,所以,若是在Re里要匹配一个字符\,须要使用\\\\四次,首先Python转移为\\进入Re,而后Re再转义成\;一个简单的方法是使用原生字符r,这样\\就好了。
例7
>>> a=re.findall('\\\\','\sabc') print(a) b=re.findall(r'\\','\sjkll') print(b) ['\\'] ['\\']
正则里面有1个基本的概念叫作贪婪模式和懒惰模式。在上面的例子里面,默认都是使用的贪婪模式,若是一个字符串里面存在多个匹配,他默认用最长的那个;懒惰模式则是对应的最短的那个匹配。懒惰模式能够经过*?或者+?或者 ??来实现。注意单独使用的?表示前面那个字符的0或者1次匹配,可是组合在一块儿就是懒惰模式了。
例8,这里 .*? 至关于一个总体,.*表示任意值,而.*?表示任意值的懒惰匹配
import re s1="hello Pythonssn" pat="p.*n" pat2="p.*?n" r1=re.search(pat,s1,re.I) r2=re.search(pat2,s1,re.I) if r1: print(r1.group()) if r2: print(r2.group()) --------- Pythonssn Python
第二个重要的概念是模式修饰符,能够在不修改模式的状况下实现一些额外的功能,常见的好比能够进行多行匹配,忽略大小写和用. 来替代换行符
例9
s2=""" python is funny, Python is not PPython; ppyhonn is Pyyon """ pat3="p.*?n" pat4="p.*n" r=re.findall(pat3,s2,re.I|re.M) r2=re.findall(pat4,s2,re.I) ------- ['python', 'Python', 'PPython', 'ppyhon', 'Pyyon'] ['python is funn', 'Python is not PPython', 'ppyhonn is Pyyon']
正则里面还有有一个概念叫作分组。简单的说,分组就是在已经匹配获取的结果里面继续划分新的子集。
在search和match里面,group表明的是获取经过pattern匹配出来的结果;groups表示分组以后的结果;groupdic一样表示分组以后的结果,不过他须要经过P?指定名字才能显示出来
例10
import re a=re.search('h(?P<name>\w+)','hello 123a hoo bc333') print(a.group()) print(a.groups()) print(a.groupdict()) ---------------- hello ('ello',) {'name': 'ello'}
在findall里面分组比较特殊,若是有分组,那么他直接就显示出分组以后的子集,而不是匹配到的字符串
例9 首先匹配到['1hh','2kll']而后分组获取数字后面部分
>>> import re a=re.findall('\d(\w+)','1hh jjkl2 hhs 2kll') print(a) ['hh', 'kll']
sub就是替换,不存在分组
split的分组以下所示
例11,对比一下不分组和分组的差异,前者分割以后不会出现分隔符,后者会显示出来
>>> a='i am ha happy man' print(re.split('am',a)) a='i am ha happy man' print(re.split('(am)',a)) ---------------- ['i ', ' ha happy man'] ['i ', 'am', ' ha happy man']
最后补充一下,正则表达式的函数除了能够直接使用re.search, re.match等形式,还能够先编译一个pattern,而后经过pattern来调用这些函数
例12 先编译一次正则表达式,而后再经过编译后的pattern来调用,这样若是调用的地方不少,能够节省一下资源
>>> import re >>> p=re.compile(r'\b\w+\b') >>> match=p.search('jkl jkljl 23jk4 kjl2') >>> print(match.group()) jkl >>> p.findall('jkl kls 234lkjk23 23lk ') ['jkl', 'kls', '234lkjk23', '23lk']
最后,给出一些经常使用的组合方式
验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0) ^\d+$
验证非正整数(负整数 + 0) ^((-\d+)|(0+))$
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$
验证用户密码:^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5],{0,}$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$:--正确格式为:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$ 正确格式为:0一、09和一、31。
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮点数(负浮点数 + 0) ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数 ^(-?\d+)(\.\d+)?$ 0 0 0