python中的正则表达式
- 正则表达式用途
正则表达式是用来(只用来)匹配字符串的;
现实操作中python的字符串内置处理函数均为绝对处理,完全匹配的操作:
s = 'hello world'
#传统的字符串内置函数均为绝对匹配
print(s.find('o'))
ret = s.replace(' ','-')
print(ret)
'''
'''
但经常在应用中需要使用到模糊匹配的情况:
如:需要用户输入电话号码:
138********
对于用户输入的一串伪电话号码的字符串,需要判断:不包含字母、区号合法(移动138、电信189等等规则)、位数正确等等;(有人说这要求使用内置函数好像可以做出了,那么继续)
如:需要留网址,邮件等
http://www.*******.com/cn
******@*****.com/.cn
此时python字符串的内置函数就完全无法对其进行模糊处理,于是python中就需要一种更加强大的字符串匹配方式----正则表达式应运而生。
-
正则表达式的方法
1、findall():将所有结果返回到一个列表中import re ret = re.findall('ll','hello world') print(ret) #['ll']2、
search():返回符合匹配的第一个
对象,对象使用group()方式返回结果import re ret = re.search('ll','hello world') print(ret) # <_sre.SRE_Match object; span=(2, 4), match='ll'> print(ret.group()) # ll3、
match:只在字符串开始匹配,符合即返回匹配到的对象import re ret = re.match('h','hello,honey') print(ret) # <_sre.SRE_Match object; span=(0, 1), match='h'> print(ret.group()) # h4、
split:按要求分割字符串import re ret = re.split('o','hello,honey') print(ret) # ['hell', ',h', 'ney']5、
sub:按要求替换字符串中指定内容import re ret = re.sub('o','O','hello,honey') print(ret) # hellO,hOney6、
compile:将所需要的匹配规则编译成一个规则对象,供其他字符串处理方法使用import re obj = re.compile('com') ret = obj.findall('www.4399.com') print(ret) # ['com'] -
正则表达式的元字符(特殊功能含义的符号)
1、.:通配符 代值一个任意字符(不包括换行符)import re # . 通配符 代指一个任意字符(不包括换号符) ret = re.findall('w..l','hello world') # 找到‘w开头中间随意两个字符,l结尾’ print(ret) # ['worl'] ret = re.findall('w.l','hello w\nld') # 换行符不包含在内 print(ret) # []2、
^:尖角符 由字符起始处开始匹配import re # ^ 尖角符 匹配开始 ret = re.findall('^h...o','hello world') # 匹配以h加任意3个字符加o开始 print(ret) # ['hello'] ret = re.match('h...o','hello world') # 从开始匹配,<_sre.SRE_Match object; span=(0, 5), match='hello'> print(ret.group()) # hello3、
$:Dollar符 匹配字符串结尾处内容import re # $ dollar符 匹配结尾 ret = re.findall('w...d$','hallo world') # 匹配以w加3个任意字符加d结尾 print(ret) # ['world']4、
*:重复匹配符 重复匹配前一个字符,数量为0到正无穷,包含0个import re # * 重复匹配符 重复匹配前面一个字符(0到∞,包括0个) ret = re.findall('a.*l','fjsdjjsljaadedlfdsf') # 匹配以a开始,多个. 即多个任意字符,l结束 print(ret) # ['aadedl'] ret = re.findall('a.*l','ddsdaljfoe') # 匹配0次 print(ret) # ['al']5、
+:重复匹配符 重复匹配前一个字符,数量为1到正无穷,包含1个import re # + 重复匹配符 重复匹配前面一个字符(1到∞,包括1个) ret = re.findall('a.+l','fjsdjjsljaadedlfdsf') # 匹配以a开始,多个. 即多个任意字符,l结束 print(ret) # ['aadedl'] ret = re.findall('a.+l','ddsdaljfoe') # 匹配0次 print(ret) # []6、
?:判断符 闭区间的[0,1] 即前一字符的数量为0或1import re # ? 闭区间的[0,1] 只取0或者1个前一个字符 ret = re.findall('a?b','gaaaabgffbn') # 匹配以0/1个a开始,b结束 print(ret) # ['ab', 'b']7、
{}:自定义区间 按自定义的区间取前一个字符import re # {} 自定义区间 按自定义区间取前一个字符 {1,}等价于+(即1到正无穷,推荐+) ret = re.findall('a{5}b','fbdaaaaabfdsffds') # 匹配5个a开始 一个b结束 print(ret) # ['aaaaab'] ret = re.findall('a{1,3}b','sddaaabf') # 匹配1到3个a开始,b结束(贪婪匹配,默认从最大的值开始匹配) print(ret) # ['aaab']以上得出如下结论:
*等于{0,正无穷} = {0,} 推荐使用*
+等于{1,正无穷} = {1,} 推荐使用+
?等于{0,1} = {0,1} 推荐使用?
8、[]:字符集 指定部分有字符集中的内容填充import re # [] 字符集 指定部分由字符集中内容填充 #ret = re.findall('a[c,d,f]x','sadxfafxd') # 匹配已a开始,c、f或d其中之一,x结束 ret = re.findall('a[cdf]x','sadxfafxd') # 匹配已a开始,c、f或d其中之一,x结束 上面错误 不要用,隔开 ,号本身就是一个字符 []中所有元素均为或的关系 print(ret) # ['adx', 'afx'] ret = re.findall('a[bcd]e','abce') print(ret) # [] 匹配a加上一个b或c或d一个字符加e 上面存在2个 ret = re.findall('[a-z]','adx') # 匹配[a-z]范围的字符,即所有小写字母 print(ret) # ['a', 'd', 'x']注意:字符集具有取消元字符特殊功能的功能,如:
import re # 字符集: 取消元字符的特殊功能 ret = re.findall('[w,*]f','asda*fds') # 匹配任意不具有含义的元字符 如已w或*开始,f结尾 print(ret) # ['*f']再次注意:取消元字符特殊功能包含三个例外:
\\转义
^^在字符集中为取反的意思[^t]即所有不为t的字符[^4,5]即所有不为4 和不为5的字符
--在字符集中具有特殊含义,代指范围,如[0-9],[a-z]等
9、():分组 把多个字符分成一组进行处理import re # () 分组 把多个字符分成一个组进行处理 print(re.search('(as)+','sdasasffsasffsf').group()) # asas 匹配第一个由1或多个个as分组 ret = re.search('(?p<id>\d{2})/(?p<name>\w{3})','123/comr') # 命名分组 print(ret.group()) # 23/com print(ret.group('id') # 23 print(ret.group('name') # com ret = re.findall('www\.(\w+)\.com','www.baidu.com') # 当分组与常用并存是 默认只返回分组里面的内容 故出现如下现象 print(ret) #['baidu'] # 解决方法 ret = re.findall('www\.(?:\w+)\.com','www.baidu.com') # 在分组最前端加?:关闭分组输出的优先级即可 print(ret) # ['www.baidu.com']10、
|管道符 或的意思import re # | 管道符 或的意思 print(re.search('(as)|g','asdfsg').group()) # as 匹配第一个由as分组或者g11、
\:反斜杠 反斜杠后面跟元字符去除元字符特殊功能 、反斜杠后面跟普通字符实现特殊功能\d匹配任何10进制数:相当于[0-9]
\D匹配任何非数字字符:相当于[^0-9]
\s匹配任何空白字符:相当于[ \t\n\f\v]
\S匹配任何非空白字符:相当于[^ \t\n\f\v]
\w匹配任何字母数字字符:相当于[a-zA-Z0-9]
\W匹配任何非字母数字字符:相当于[^a-zA-Z0-9]
\b匹配一个特殊边界,指单词和空格间的位置,或者特使字符¥%#等等import re print(re.findall('\d{4}','dsa39428')) #['3942'] print(re.findall('\sgao','fdk gao')) #[' gao'] print(re.findall('\wgao','dhsagao')) #['agao'] print(re.findall(r'\bI','hello,I am a LIST')) #['I'] 如果后面一个LIST中的I后面跟的是特殊字符,也可以取到 print(re.search('a.','adfks').group()) # ab print(re.search('a\.','adfks')) # None print(re.search('a\.','a.dfks').group()) # a. -
补充
有关贪婪匹配与惰性匹配
前面是*、+、?等都是贪婪匹配,也就是尽可能匹配,后面加?使其变成惰性匹配
import re
ret = re.findall('ab*','abbbj') # 贪婪匹配
print(ret) # ['abbb']
ret = re.findall('ab*?','abbbj') # 惰性匹配
print(ret) # ['a']
最后使用正则表达式写一个简单的计算器,不够完善,多多包涵:
#!-*- coding:utf-8 -*-
#date: 2020/4/18
# 计算器代码
import re
def add(a,b):
print('%f+%f=%f'%(a,b,a+b))
return a + b
def sub(a,b):
print('%f-%f=%f' % (a, b, a - b))
return a - b
def mul(a,b):
print('%f*%f=%f' % (a, b, a * b))
return a * b
def div(a,b):
print('%f/%f=%f' % (a, b, a / b))
return a / b
def spilt_num(x):
# print(x)
if '+' in x:
num = x.split('+')
return add(float(num[0]),float(num[1]))
elif '-' in x:
num = x.split('-')
return sub(float(num[0]), float(num[1]))
elif '*' in x:
num = x.split('*')
return mul(float(num[0]), float(num[1]))
elif '/' in x:
num = x.split('/')
return div(float(num[0]), float(num[1]))
def search_first(x):
ret = re.search('\([^()]+\)',x)
if ret:
return ret.group()
else:
return None
def search_second(x):
ret = re.search('(\d+\.?\d*[\*,/]\d+\.?\d*)',x)
if ret:
return ret.group()
else:
return None
def search_third(x):
ret = re.search('(\d+\.?\d*[\+,\-]\d+\.?\d*)',x)
if ret:
return ret.group()
else:
return None
def search_begin(x):
if re.match('-\d+\.?\d*\+',x):
s = re.match('-\d+\.?\d*\+\d+\.?\d*', x).group().split('+')
a = re.match('-\d+\.?\d*\+\d+\.?\d*', x).group()
s = s[1]+s[0]
# print(s)
return s,a
elif re.match('-\d+\.?\d*\-',x):
s = re.match('-\d+\.?\d*\-\d+\.?\d*', x).group().split('-')
a = re.match('-\d+\.?\d*\-\d+\.?\d*', x).group()
# print(s)
s = '-' + str(float(s[1]) + float(s[2]))
# print(s)
return s,a
else:
return None
# search_begin('-1+2')
if __name__ == '__main__':
while True:
s = input('请输入你需要计算的式子:')
if re.search('[a-zA-z\s]',s):
# print(re.search('[a-zA-Z]',s))
print('error')
break
a = s
while True:
if search_first(s):
first = search_first(s)
first1 = first.replace('(','').replace(')','')
# print(first1)
while True:
if search_second(first1):
first2 = search_second(first1)
first2_get = spilt_num(first2)
first1 = first1.replace(first2,str(first2_get))
# print(first1)
continue
elif search_begin(first1):
first2 = search_begin(first1)
first1 = first1.replace(first2[1], first2[0])
# print(first1)
continue
elif search_third(first1):
first2 = search_third(first1)
first2_get = spilt_num(first2)
first1 = first1.replace(first2, str(first2_get))
# print(first1)
continue
elif first1.find('--')!=-1:
# print(first1)
first1 = first1.replace('--','+')
# print(first1)
continue
else:
# print(first1)
break
s = s.replace(first,first1)
# print(s)
continue
elif search_second(s):
second2 = search_second(s)
# if second2.find('*')!=-1:
second2_get = spilt_num(second2)
s = s.replace(second2,str(second2_get))
# print(s)
continue
elif search_begin(s):
begin1 = search_begin(s)
# print(begin1)
s = s.replace(begin1[1], begin1[0])
# print("@",s)
continue
elif search_third(s):
third3 = search_third(s)
third3_get = spilt_num(third3)
s = s.replace(third3,str(third3_get))
# print("!",s)
continue
elif s.find('--') != -1:
# print(s)
s = s.replace('--','+')
# print(s)
continue
else:
print('%s=%s'%(a,s))
break
# 本代码仅供参考
3700



被折叠的 条评论
为什么被折叠?



