Python 常用模块之re 正则表达式的使用

时间:2021-05-29 22:34:37

re模块用来使用正则表达式。正则表达式用来对字符串进行搜索的工作。我们最应该掌握正则表达式的查询,更改,删除的功能。特别是做爬虫的时候,re模块就显得格外重要。

1.查询

1 import re
2 a = re.match("abc","aabccc")
3 b = re.search("abc","aabcc")
4 print("a =",a)
5 print("b =",b)

 

运行结果: a = None b = <_sre.SRE_Match object; span=(1, 4), match='abc'>

 

re.match是从字符串开头开始匹配,如果和匹配字符不同,即便字符串内包含相同内容,返回值也为空。而re.search是匹配字符串内,只要字符串内包含被搜索内容,就有返回值。

这里,查询的结论是无的话,返回值就是None。我们可以把它和if或者while等循环配合起来使用,如果需要调用搜寻结果,需要在返回值后加.group()。

1 a = ["abcdef","aaccd","aadfa","adffadsfabc"]
2 for i in a:
3     if re.search("abc",i):
4         print("%s内包含:%s"%(i,re.search("abc",i).group()))
运行结果:
abcdef内包含:abc adffadsfabc内包含:abc

还有一种查询方法 

1 a = "123456789aaa123aaa654"
2 print(re.findall("aaa",a))
运行结果: ['aaa', 'aaa']

re.findall就是把字符串内所有的关键字都搜索出来生成列表输出。

2.更改

1 a = "123456789aaa123aaa654"
2 print("全部更改:",re.sub("aaa","bbb",a))
3 print("更改指定次数:",re.sub("aaa","bbb",a,count=1))
4 print("删除搜索内容:",re.sub("aaa","",a))
运行结果: 全部更改: 123456789bbb123bbb654 更改指定次数: 123456789bbb123aaa654 删除搜索内容: 123456789123654

用re.sub可以对对字符串进行更改或删除的操作。注意re.sub后没有.group()的用法。

此外还有一个分割的用法:

1 a = "123456789aaa123aaa654"
2 print(re.split("aaa",a))
运行结果: ['123456789', '123', '654']

将原字符串按照搜索的关键字分割成一个列表输出。


                                                    分                          割                                    线                                                                           


掌握了最基础的语法后,我们要了解一下较为复杂的正则表达式的使用方法了:

首先,我们要先了解正则表达式的表达符号

'.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$'     匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?'     匹配前一个字符1次或0次
'{m}'   匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,匹配到先出现的就停止。
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c

还有一些搜索方式

'\A'    只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z'    匹配字符结尾,同$
'\d'    匹配数字0-9
'\D'    匹配非数字
'\w'    匹配[A-Za-z0-9]
'\W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
'(?P<name>...)' 分组匹配 
(?P<name>...)分组匹配:相当于每个关键字前加一个key生成一个字典,比方我们要匹配一个身份证号,匹配规则是前六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
1 ID = "410110199912121234"
2 a = re.search("(?P<address>[0-9]{6})(?P<birthday>[0-9]{8})(?P<order>[0-9]{3})(?P<check>[0-9]{1})",ID).groupdict()
3 print(a)
运行结果: {'address': '410110', 'birthday': '19991212', 'order': '123', 'check': '4'}

 

现在,我们可以举个栗子吧了:我们想做一个加法计算器,第一步就是要把两个计算的加数搜索出来,最简单的方式是这样:

1 import re
2 cul = "123+456"
3 a = re.search("\d+[+]",cul).group()[:-1]
4 b = re.search("[+]\d+",cul).group()[1:]
5 print("a = %s,b = %s"%(a,b))
运行结果: a = 123,b = 456

我们在返回值里用了切片的方法,删除了返回值中的加号“+”。

这时候再想一想:要是a或b之间有小数点怎么办?用这样的方法就不行了吧!我们把cul赋值为"1.23+3.45"运行一下:

运行结果:
a = 23,b = 4

明显不对了,怎么办呢?需要把小数点也加进去

1 import re
2 cul = "1.23+4.56"
3 a = re.search("\d+[.]\d+[+]",cul).group()[:-1]
4 b = re.search("[+]\d+[.]\d+",cul).group()[1:]
5 print("a = %s,b = %s"%(a,b))
运行结果: a = 1.23,b = 4.56

可是还有个问题,小数点不是每次都有啊,怎么让它自己判断呢?可以加个”?“

1 import re
2 def add(cul):
3     a = re.search("(\d+)?[.]?\d+[+]",cul).group()[:-1]
4     b = re.search("[+]\d+[.]?(\d+)?",cul).group()[1:]
5     print("a = %s,b = %s"%(a,b))
6 add("1.23+4.56")
7 add("123+456")
运行结果:
add("1.23+4.56") add("123+456")

这里有个很关键的问题:

  正则表达式中的字符采用的是转义字符,如果需要匹配的字符为"aa\\bb\\cc"时,每个"\"前都须加一个"\",就成了"aa\\\\bb\\\\cc"在匹配字符串内有”+“、”*“时都需要加上反斜杠。我们可以把匹配的字符串前加"r",就可以不用在每个"\"前都再加上"\",程序也更加直观。

 此外,我们还可以把变量套进正则表达式中

1 import re
2 ans = "2"
3 cul = "(6-4)*2"
4 cul2 = "6-4"
5 print("简化后:",re.sub("[(]%s[)]"%cul2,ans,cul))#匹配的表达式为一个变量
运行结果: 简化后: 2*2

但这里要注意一下:如果表达式内有加号或乘号时是不能这样使用的,即便在表达式前加"r"也不行,必须把+换成\+

1 import re
2 ans = "10"
3 cul = "(6+4)*2"
4 cul2 = "6\+4"  #这个地方的+或*必须用\+或\*
5 print("简化后:",re.sub("[(]%s[)]"%cul2,ans,cul))
运行结果: 简化后: 10*2
 

还有一些更复杂的方法,需要我们慢慢研究吧!