[python标准库]Re模块

时间:2022-03-13 02:38:54

本文主要讲述以下几个方面:

  1.元字符

  2.贪婪匹配

  3.实例

1.元字符

'.'      匹配任意一个字符,除换行符
'^' 匹配以一个字符开头的字符串
‘$’ 匹配一个字符串的结尾
import re

ret1
=re.findall('李.','李爽\nalex\n李四\negon\nalvin\n李二')

ret2
=re.findall('^李.','李爽\nalex\n李四\negon\nalvin\n李二')

ret3
=re.findall('李.$','李爽\nalex\n李四\negon\nalvin\n李二')

ret4=re.findall('a.b','a\nb',re.S)) #['a\nb'] //re.S输出换行符
'*'     匹配前面一个字符0至无穷次数
'+' 匹配前面一个字符1至无穷次数
'?' 匹配前面一个字符0或1次
'{}' 匹配前面一个字符指定次数。{m,n},匹配前面字符m至n次
[python标准库]Re模块[python标准库]Re模块
#*
print(re.findall('ab*','bbbbbbb')) #[]
print(re.findall('ab*','a')) #['a']
print(re.findall('ab*','abbbb')) #['abbbb']

#?
print(re.findall('ab?','a')) #['a']
print(re.findall('ab?','abbb')) #['ab']
#
匹配所有包含小数在内的数字
print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']

print(re.findall('ab+','a')) #[]
print(re.findall('ab+','abbb')) #['abbb']

#{n,m}
print(re.findall('ab{2}','abbb')) #['abb']
print(re.findall('ab{2,4}','abbb')) #['abb']
print(re.findall('ab{1,}','abbb')) #'ab{1,}' ===> 'ab+'
print(re.findall('ab{0,}','abbb')) #'ab{0,}' ===> 'ab*'
实例

注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

ret=re.findall('131\d+?','1312312312')
print(ret) ['1312']
‘\’  转义字符

1、反斜杠后边跟元字符去除特殊功能,比如\.

2、反斜杠后边跟普通字符实现特殊功能,比如\d

[python标准库]Re模块[python标准库]Re模块
\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 匹配一个特殊字符边界,比如空格 ,
&,#等
常见的转义字符
[python标准库]Re模块[python标准库]Re模块
#正则匹配
import re
#\w与\W
print(re.findall('\w','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
print(re.findall('\W','hello egon 123')) #[' ', ' ']

#\s与\S
print(re.findall('\s','hello egon 123')) #[' ', ' ', ' ', ' ']
print(re.findall('\S','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']

#\d与\D
print(re.findall('\d','hello egon 123')) #['1', '2', '3']
print(re.findall('\D','hello egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', 'e', 'g', 'o', 'n', ' ']

#\A与\D
print(re.findall('\Ahe','hello egon 123')) #['he'],\A==>^
print(re.findall('123\Z','hello egon 123')) #['he'],\Z==>$

#\n与\t
print(re.findall(r'\n','hello egon \n123')) #['\n']
print(re.findall(r'\t','hello egon\t123')) #['\n']
实例

特别注意:

[python标准库]Re模块[python标准库]Re模块
import re

ret
=re.findall('c\l','abc\le')
print(ret)#[]

ret
=re.findall('c\\l','abc\le')
print(ret)#[]

ret
=re.findall('c\\\\l','abc\le')
print(ret)#[]

ret
=re.findall(r'c\\l','abc\le')
print(ret)#[]


# \b是特殊符号所以,'abc\be'前面需要加r
ret=re.findall(r'c\\b',r'abc\be')
print(ret)#[]
实例
‘()’   分组
'[]' 字符集
'|' 逻辑或
[python标准库]Re模块[python标准库]Re模块
#[]
print(re.findall('a[1*-]b','a1b a*b a-b')) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾
print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]内的^代表的意思是取反,所以结果为['a=b']


#():分组
print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']
print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab
print(re.findall('(?:ab)+123','ababab123')) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容

print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))
实例
[python标准库]Re模块[python标准库]Re模块
#--------------------------------------------字符集[]
ret=re.findall('a[bc]d','acd')
print(ret)#['acd']

ret
=re.findall('[a-z]','acd')
print(ret)#['a', 'c', 'd']

ret
=re.findall('[.*+]','a.cd+')
print(ret)#['.', '+']

#在字符集里有功能的符号: - ^ \

ret
=re.findall('[1-9]','45dha3')
print(ret)#['4', '5', '3']

ret
=re.findall('[^ab]','45bdha3')
print(ret)#['4', '5', 'd', 'h', '3']

ret
=re.findall('[\d]','45bdha3')
print(ret)#['4', '5', '3']
实例

说明:对于分组情况,如果括号比较多,可以先不考虑括号,按照最原始的规则进行匹配。拿到匹配后的信息,再对其进行分组即可。

贪婪匹配

贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
string pattern1 = @"a.*c";   // greedy match 
Regex regex
= new Regex(pattern1);
regex.Match(
"abcabc"); // return "abcabc"
非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配

string pattern1
= @"a.*?c"; // non-greedy match
Regex regex
= new Regex(pattern1);
regex.Match(
"abcabc"); // return "abc"
几个常用的非贪婪匹配Pattern
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法:
. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.
*?x

就是取前面任意长度的字符,直到一个x出现
#.*默认为贪婪匹配
print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']

#.*?为非贪婪匹配:推荐使用
print(re.findall('a.*?b','a1b22222222b')) #['a1b']

re模块下的常用方法

[python标准库]Re模块[python标准库]Re模块
import re

re.findall(
'a','alvin yuan') #返回所有满足匹配条件的结果,放在列表里

re.search(
'a','alvin yuan').group()

#函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。



re.match(
'a','abc').group() #同search,不过尽在字符串开始处进行匹配


ret
=re.split('[ab]','abcd') #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割

print(ret)#['', '', 'cd']


ret
=re.sub('\d','abc','alvin5yuan6',1)

ret
=re.subn('\d','abc','alvin5yuan6')



obj
=re.compile('\d{3}')
ret
=obj.search('abc123eeee')
print(ret.group())#123


import re
ret
=re.finditer('\d','ds3sy4784a')
print(ret) #<callable_iterator object at 0x10195f940>

print(next(ret).group())
print(next(ret).group())
View Code
[python标准库]Re模块[python标准库]Re模块
import re
#1
print(re.findall('e','alex make love') ) #['e', 'e', 'e'],返回所有满足匹配条件的结果,放在列表里
#
2
print(re.search('e','alex make love').group()) #e,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

#3
print(re.match('e','alex make love')) #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match

#4
print(re.split('[ab]','abcd')) #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割

#5
print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默认替换所有
print('===>',re.sub('a','A','alex make love',1)) #===> Alex make love
print('===>',re.sub('a','A','alex make love',2)) #===> Alex mAke love
print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','alex make love')) #===> love make alex

print('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),结果带有总共替换的个数


#6
obj=re.compile('\d{2}')

print(obj.search('abc123eeee').group()) #12
print(obj.findall('abc123eeee')) #['12'],重用了obj
View Code

注意:

1 findall的优先级查询:

import re

ret
=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
print(ret)#['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret
=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
print(ret)#['www.oldboy.com']

2 split的优先级查询

ret=re.split("\d+","yuan2egon56alex")
print(ret)

ret
=re.split("(\d+)","yuan2egon56alex")
print(ret)

3.实例

[python标准库]Re模块[python标准库]Re模块
import re
print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")) #['h1']
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").group()) #<h1>hello</h1>
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").groupdict()) #<h1>hello</h1>

print(re.search(r"<(\w+)>\w+</(\w+)>","<h1>hello</h1>").group())
print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>").group())
View Code
[python标准库]Re模块[python标准库]Re模块
import re

print(re.findall(r'-?\d+\.?\d*',"1-12*(60+(-40.35/5)-(-4*3))")) #找出所有数字['1', '-12', '60', '-40.35', '5', '-4', '3']


#使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所有即使匹配成功小数也不会存入结果
#
而不是小数时,就去匹配(-?\d+),匹配到的自然就是,非小数的数,在此处即整数
print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整数['1', '-2', '60', '', '5', '-4', '3']
View Code
[python标准库]Re模块[python标准库]Re模块
import re

s
='''
http://www.baidu.com
1011010101
egon@oldboyedu.com
你好
21213
010-3141
'''

#最常规匹配
#
content='Hello 123 456 World_This is a Regex Demo'
#
res=re.match('Hello\s\d\d\d\s\d{3}\s\w{10}.*Demo',content)
#
print(res)
#
print(res.group())
#
print(res.span())

#泛匹配
#
content='Hello 123 456 World_This is a Regex Demo'
#
res=re.match('^Hello.*Demo',content)
#
print(res.group())


#匹配目标,获得指定数据

# content='Hello 123 456 World_This is a Regex Demo'
#
res=re.match('^Hello\s(\d+)\s(\d+)\s.*Demo',content)
#
print(res.group()) #取所有匹配的内容
#
print(res.group(1)) #取匹配的第一个括号内的内容
#
print(res.group(2)) #去陪陪的第二个括号内的内容



#贪婪匹配:.*代表匹配尽可能多的字符
#
import re
#
content='Hello 123 456 World_This is a Regex Demo'
#
#
res=re.match('^He.*(\d+).*Demo$',content)
#
print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字


#非贪婪匹配:?匹配尽可能少的字符
#
import re
#
content='Hello 123 456 World_This is a Regex Demo'
#
#
res=re.match('^He.*?(\d+).*Demo$',content)
#
print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字


#匹配模式:.不能匹配换行符
content='''Hello 123456 World_This
is a Regex Demo
'''
# res=re.match('He.*?(\d+).*?Demo$',content)
#
print(res) #输出None

# res=re.match('He.*?(\d+).*?Demo$',content,re.S) #re.S让.可以匹配换行符
#
print(res)
#
print(res.group(1))


#转义:\

# content='price is $5.00'
#
res=re.match('price is $5.00',content)
#
print(res)
#
#
res=re.match('price is \$5\.00',content)
#
print(res)


#总结:尽量精简,详细的如下
# 尽量使用泛匹配模式.*
# 尽量使用非贪婪模式:.*?
# 使用括号得到匹配目标:用group(n)去取得结果
# 有换行符就用re.S:修改模式
View Code
正则匹配实现计算器
import re

def rekuo(x): # 主体
while True:
ret
= re.search(r'\(([^()]+)\)',x) # 正则判断括号,提取括号内容
# print(ret)
if ret:
p
= count(ret.group(1)) # 括号内容内容计算
x = x.replace(ret.group(), p) # 计算后的答案,替换原先的括号内容
else: # 正则匹配没用括号的话
p = count(x) # 公式计算,得出答案
return p # 输出结果


def count(s): #计算函数
while True:
ret
= re.search(r'(?P<float1>[\-]?\d+\.?\d*)[ ]*(?P<symbol>[*/])[ ]*(?P<float2>[\-]?\d+\.?\d*)',s)
if ret: # 如果包含乘除法先计算乘除法
if ret.group('symbol') == '*': #乘法
p = str(float(ret.group('float1')) * float(ret.group('float2')))
else: #除法
try:
p
= str(float(ret.group('float1')) / float(ret.group('float2')))
except ZeroDivisionError as e:
print('除数不能为零', e)
s
= s.replace(ret.group(),p,1) #结果替换原先内容
continue #结束当前循环
ret = re.search(r'(?P<float1>[\-]?\d+\.?\d*)[ ]*(?P<symbol>[+-]{1})[ ]*(?P<float2>[\-]?\d+\.?\d*)',s)
if ret: # 加减法运算
if ret.group('symbol') == '-': # 减法
p = str(float(ret.group('float1')) - float(ret.group('float2')))
elif ret.group('symbol') == '+': # 加法
p = str(float(ret.group('float1')) + float(ret.group('float2')))
s
= s.replace(ret.group(),p,1)
continue
return s #输出结果
s = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
print(eval(s))
print(rekuo(s))