在Python里面,处理字符串除了基本的split,格式化操作等等,还可以使用正则表达式。使用正则表达式,需要导入模块re。正则本身也是一门语言,像下围棋一样,入门很容易,不过要玩的很溜就得花时间了。

老实说,老男孩13期的正则表达式的视频真的很烂,那个讲课的估计是个新人,说话颠三倒四,逻辑混乱,豆子听完还是稀里糊涂。

课后在网上找到一篇强文

拜读之后,受益匪浅。

基本规则如下所示:

re模块有下面几个常用的函数

1. findall(pattern, string, flags=0),这个函数会返回一个列表,列表的元素是匹配到的字符串

例1,下面会匹配出以a开头的所有单词,\w+表示一个或者多个字母数字或者下划线,因为不包括空格,所以相当于单个的单词了

>>> import reret=re.findall('a\w+','abc aaa bbh kjk hkk add')print(ret)['abc', 'aaa', 'add']

例2,在字符集里面的元素可以表示或的意义。字符集里面特殊的字符会失去意义;但是他本身有2个特殊的字符,-表示范围,^表示取反,比如说我需要查找加减乘除的符号,那么-因为有特殊含义,因此需要用转移符\转义

>>> import rea=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 reobj = re.search('\d+', '123uuasf')if obj:    print(obj.group())-------------123

3. match(pattern,string,flags)会通过pattern去匹配,如果匹配成功,会返回一个match对象,否则返回None。然后可以通过group()函数获取对象里面的字符串。他和search的区别在于match只能匹配字符串开头的字符,后面的无法匹配;而search可以匹配到任意位置的字符串。

例4

import reobj = 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 res1="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()) ---------PythonssnPython

第二个重要的概念是模式修饰符,可以在不修改模式的情况下实现一些额外的功能,常见的比如可以进行多行匹配,忽略大小写和用. 来替代换行符

例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 rea=re.search('h(?P
\w+)','hello 123a hoo bc333')print(a.group())print(a.groups())print(a.groupdict())----------------hello('ello',){'name': 'ello'}

在findall里面分组比较特殊,如果有分组,那么他直接就显示出分组之后的子集,而不是匹配到的字符串

例9 首先匹配到['1hh','2kll']然后分组获取数字后面部分

>>> import rea=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']