正则表达式
正则表达式
一.认识正则表达式
正则表达式是什么 ?
正则表达式是一门单独的语音,不仅属python,很多语言都可以调用它,它自成体系
正则表达式有什么用呢?
首先我们看一下python自带的字符串的一些功能方法
str1 = "abcdefg"
result1 = str1.find("b")
result2 = str1.find("bc")
result3 = str1.split("b")
result4 = str1.replace("ab", "AB")
print("b的位置是:%s" % result1)
print("bc的位置是:%s" % result2)
print("字符串以b分割成:%s" % result3)
print("字符串替换后的结果是:%s" % result4)
我们可以观察得到,无论是查找,分割,或者替换都需要明确具体的元素
而正则表达式可以给出一个pattern,符合要求的可以有很多,不仅仅局限唯一
二.正则表达式的元字符及其意义
. :匹配任意除换行符的单个字符
^:行首锚定
$:行尾锚定
*:匹配任意次,贪婪匹配 等价于{0,}
+:匹配1到多次,贪婪匹配 降价与{1,}
?:匹配0或1次,贪婪匹配 降价与{0,1}
{}:固定次数
{3}:3次
{3,5}:3到5次
\:
1.反斜杠后边跟元字符去掉特殊功能
2.反斜杠后边跟普通字符实现特殊功能
\d:匹配任何单个十进制数,它相当于类[0-9],匹配一个数字
\D:匹配任何单个非数字字符,它相当于[^0-9]
\s:匹配任何单个空白字符,它相当于类[ \t\n\r\f\v]
\S:匹配任何单个非空白字符,它相当于[^ \t\n\r\f\v]
\w:匹配任何单个字母数字字符;它相当于类[a-zA-Z0-9]
\W:匹配任何单个非字母数字字符,它相当于类[^a-zA-Z0-9]
\b:匹配一个单词边界,也就是指单词和空格间的位置
3.引用序号对应的字组所匹配的字符串
re.search(r"(alex)(eric)com\2", "alexericcomeric").group()
'alexericcomeric'
[]:字符集中的任意一个,字符集中的元字符不用转义
^:字符集中的^表示非
re.findall('[^1-9]','a1b2c3')
['a', 'b', 'c']
\:转义的普通字符\d,\w,\s等用法不变
re.findall('[\d]','ww3 wa8.d0')
['1', '2', '3']
():分组,将一串字符做为一个整体
贪婪模式:
re.search(r"a(\d+)","a12345678b").group()
a12345678
非贪婪模式:
re.serach(r"a(\d+?)","a12345678b").group()
a1
三.贪婪模式的存在机制
re.findall(r"a(\d+?)", "a23b") #非贪婪模式
['2'] #匹配括号里面的
re.findall(r"a(\d+)b", "a23b") #如果前后均有限定条件,则不按非贪婪模式匹配
['23']
re.findall(r"a(\d+?)b", "a23b") #如果前后均有限定条件,则不按非贪婪模式匹配
['23']
re.findall(r"a(\d+)", "a23b") #贪婪模式
['23']
四.rawstring原生字符串
正则机制:在正则表达式中,python编译器先拿到pattern里面的内容,编译后再传给正则表达式从而匹配到
符合要求的字符串
例1:
import re
result = re.findall("\\\\", 'abc\com')
'''
为了匹配到\,又因为\为正则元字符,python中\也有特殊意义
python编译器拿到4个\先转义成2个\,交给正则的编译器
2个\再转义成一个无意义的字符\,即可匹配到\
'''
print(result)
'''
匹配结果为['\\']
这是python对元字符匹配后的显示方法
'''
result1 = re.findall(r"\\", 'abc\com')
'''
引入原生字符串,直接将2个\交给正则表达式去解析
'''
print(result1)
例2:
import re
result1 = re.findall("\d", 'a1b2c3')
print(result1)
'''
['1', '2', '3']
本身需要转义的\d,却依然成功匹配的原因是:
python中没有\d这个转义字符,没有产生冲突
'''
result2 = re.findall("\\d", 'a1b2c3')
'''
那么加上\\也不影响结果
'''
print(result2)
result3 = re.findall(r"\d", 'a1b2c3')
'''
加入原生字符串的效果依然是一样
'''
print(result3)
例3:
import re
result1 = re.match('\bblow', 'blow')
'''
python中\b为删除符,有特殊意思,所以直接如上写法无法得到匹配结果
'''
print(result1) #None
result2 = re.match('\\bblow', 'blow')
'''
给\b加上转义符,由python转换成\b
再由正则解释成自己的独特的意义
'''
print(result2.group()) #blow
result3 = re.match(r'\bblow', 'blow') #同理,引入原生字符之后
print(result2.group())
五. 正则表达式是的基本方法
1.re.match()
import re
# re.match() 从头匹配,返回一个对象
# 无分组匹配
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("h\w+", origin)
print(r.group()) # 获取匹配到的所有结果(无分组时,只有group有意义)
print(r.groups()) # 获取模型中匹配到的分组结果,无意义
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
'''
hello
()
{}
'''
# 有分组匹配
r = re.match("(h)(\w+)", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果,分组才有意义
r = re.match("(?P<n1>h)(?P<n2>\w+)", origin)
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组,分组才有意义
'''
hello
('h', 'ello')
{'n1': 'h', 'n2': 'ello'}
'''
2.re.search()
import re
#re.search() 浏览全部字符串,匹配第一个合法的字符串,返回一个对象
#无分组匹配
origin = "hello alex bcd alex lge alex acd 19"
r = re.search("a\w+", origin)
print(r.group()) #获取匹配到的所有结果(无分组时,只有group有意义)
print(r.groups()) #获取模型中匹配到的分组结果,无意义
print(r.groupdict()) #获取模型中匹配到的分组中所有执行了key的组
'''
alex
()
{}
'''
#有分组匹配
r = re.search("a(\w+).*(?P<name>\d)$", origin)
print(r.group()) #获取匹配到的所有结果
print(r.groups()) #获取模型中匹配到的分组结果,分组才有意义
print(r.groupdict()) #获取模型中匹配到的分组中所有执行了key的组
'''
alex bcd alex lge alex acd 19
('lex', '9')
{'name': '9'}
'''
3.re.findall()
import re
origin = "a2b3c4d5"
result = re.findall("\d+\w\d+", origin)
print(result)
'''
['2b3', '4d5']
'''
#无分组
origin = "hello alex bcd alex lge alex acd 19"
r = re.findall("a\w+", origin)
print(r)
'''
['alex', 'alex', 'alex', 'acd']
'''
#有分组
origin = "hello alex bcd alex lge alex acd 19"
#优先捕获
r = re.findall("a(\w+)", origin)
print(r)
'''
['lex', 'lex', 'lex', 'cd']
'''
r = re.findall("(a)(\w+)", origin)
print(r)
'''
['lex', 'lex', 'lex', 'cd']
'''
#去除优先捕获加 ?:
r = re.findall("a(?:\w+)", origin)
print(r)
'''
['alex', 'alex', 'alex', 'acd']
'''
#内嵌分组:从左到右,从外到里,有几个括号取几次
r = re.findall("(a)(\w+(e))(x)", origin)
print(r)
'''
[('a', 'le', 'e', 'x'), ('a', 'le', 'e', 'x'), ('a', 'le', 'e', 'x')]
'''
4.re.finditer()
import re
#finditer每次迭代的时候,内容才会创建
origin = "hello alex bcd alex lge alex acd 19"
r = re.finditer("(a)(\w+(e))(x)", origin)
print(r)
for i in r:
print(i, i.group(), i.groups(), i.groupdict())
'''
<callable_iterator object at 0x020F90F0>
<_sre.SRE_Match object; span=(6, 10), match='alex'> alex ('a', 'le', 'e', 'x') {}
<_sre.SRE_Match object; span=(15, 19), match='alex'> alex ('a', 'le', 'e', 'x') {}
<_sre.SRE_Match object; span=(24, 28), match='alex'> alex ('a', 'le', 'e', 'x') {}
'''
5.re.split() 可指定分割次数
import re #re.split 可指定分割次数 origin = "hello alex bcd abcd lge acd 19" #无分组 不包含做为分割的那个字符串 n = re.split("a\w+", origin) print(n) ''' ['hello ', ' bcd ', ' lge ', ' 19'] ''' #有分组 显示分组里的内容 n = re.split("(a\w+)",origin) print(n) ''' ['hello ', 'alex', ' bcd ', 'abcd', ' lge ', 'acd', ' 19'] '''
#分割流程:split
#p = re.compile(r"\d+")
#p.split('one1two2three3four4')
#['one', 'two', 'three', 'four', '']
#首先找到1,分成one,two2three3four4
#然后找到2,分成two,three3four4
#然后找到3,分称three,four4
#最后找到4,分成four,和 空
6.re.sub()与re.subn()
import re
#正则中替换用sub ,subn(将替换后字符串和替换次数放在一个元组里面)
#re.sub(pattern, repl, string, max=0) max为替换次数
re.sub("g.t", "have", "i get A, i got B, I gut C",max = 2)
#"i have A, i have B, I gut C"
new,count = re.subn("g.t", "have", "i get A, i got B, I gut C")
print(new,count)
#("i have A, i have B, I have C",3)
7.总结
#search与match一旦匹配成功,就是返回一个对象,对象的常用方法如下
import re
a = '123abc456'
r1 = re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0) # 123abc456
r2 = re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1) # 123
r3 = re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2) # abc
r4 = re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(3) # 456
#start() 返回匹配开始的位置
#end() 返回匹配结束的位置
#span() 返回一个元组,包含匹配(开始,结束)的位置
六.常见的正则表达式
IP:
^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
手机号:
^1[3|4|5|8][0-9]\d{8}$
邮箱:
[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+
七.课后作业,计算器开发
re.split("\([^()]+\)", expression) ()有特殊意义,表示分组,[]里面的符号都没有特殊意义,不需要转义
def f1(ex):
pass
origin = "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) "
while True:
result = re.split("\(([^()]+)\)",origin,1)
if len(result) == 3:
#before = result[0]
#content = result[1]
#after = result[2]
before,content,after = result
r = f1(content)
new_str = before + r + after
origin = new_str
else:
final = f1(result[0])
print(final)
print(origin)
break
计算1*2+3*4+5*6+..+99*100的值
# 1*2+3*4+5*6+7*8+9*10 import re def f1(arg): arg1, arg2 = arg.split('*') r = (int(arg1)) * (int(arg2)) return str(r) def seq(arg1, arg2): seq = '' for i in range(arg1, arg2): if i % 2 == 0 and i != arg2 - 1: seq = seq + str(i) + '+' elif i % 2 != 0: seq = seq + str(i) + '*' else: seq = seq + str(i) return seq def add1(data): summ = 0 ret = data.split('+') for i in ret: summ = int(i) + summ return summ if __name__ == '__main__': a = int(input("输入一下格式:1*2+3*4+5*6+7*8+9*10,首:")) b = int(input("输入一下格式:1*2+3*4+5*6+7*8+9*10,尾:")) seq1 = seq(a, b + 1) while True: result = re.split(r'(\d{1,2}\*\d{1,2})', seq1, 1) if len(result) == 3: # print(result) before = result[0] content = result[1] after = result[2] r = f1(content) new_str = before + r + after seq1 = new_str else: # print(result) # print(seq1) break result = add1(seq1) print(result)