python #正则表达式 #re #全教程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44925501/article/details/102469506

正则表达式

Talk is cheap. Show me the code.

import re
#注:介绍方法过后,==>是对参数的解释

#re: 查找母串是否含某子串,母串中提取子串,匹配的子串进行替换操作
'''正则表达式:一种特殊规则的字符串,特殊之处在二:一是,它是按照某种规则进行的
,可能不只有一个值。二是,它有对应的方法,match。换句话说,正则表达式就是一个用于匹配字符串的模板'''



'''上面这种预编译用到正则表达式对象,更加强大。'''
print('第零部分:这只是个示例')
#预编译正则表达式(预编译的好处是,可以多次调用)
#re.compile('string') ==>子串
#p是.pattern对象的实例,是一个缓存
p = re.compile('abc')
#调用这个实例的方法search('string')==>母串
a = p.search('www.abc.com')
print(a)#可以看到    <_sre.SRE_Match object; span=(4, 7), match='abc'>
#span()返回匹配的位置,group()返回匹配的组  如下两行:
print(a.span())
print(a.group())

#不使用预编译的话,上面也可以这样写
a = re.search('abc','www.abc.com')







print('\n第一部分:只返回一处 match 和 search ')
#re.match(pattern,string,flags=0) ==>正则,母串,旗标
#match:从开始位置匹配,不成功返回none,成功则返回一个Match对象
m1 = re.match('www','www.fkit.org')
print(m1)
print(m1.span())
print(m1.group())

#re.search(pattern,string,flags=0) ==>正则,母串,旗标
#search:扫描整个,不成功返回none,成功返回match对象
m2 = re.search('fkit','www.fkit.org')
print(m2)
print(m2.span())
print(m2.group())






print('\n第二部分:返回多处 findall 和 finditer ')
#re.findall(pattern,string,flags=0) ==>正则,母串,旗标
#findall:扫描整个,返回所有匹配正则的子串的列表
m3 = re.findall('hello','hello world,hello python')
print(m3)

#re.finditer(pattern,string,flags=0) ==>正则,母串,旗标
#finditer:扫描整个,返回所有匹配正则的子串的迭代器
m4 = re.finditer('hello','hello world,hello python')
for m4_ in m4:
    print(m4_)#会打印两个match对象






print('\n第三部分:全匹配与替换 fullmatch 和 sub ')
#re.fullmatch(pattern,string,flags=0) ==>正则,母串,旗标
#fullmatch:扫描整个,要求母串等于子串,不等返回none,等于返回match
m5 = re.fullmatch('hello','hello world,hello python')
print(m5)

#re.sub(pattern,repl,string,count=0,flags=0) 
# ==>正则,用于替换的,母串,替换次数(为零则全换),旗标
#sub:扫描整个,要求母串等于子串,不等返回none,等于返回match
m6 = re.sub('-','/','2019-10-8')
print(m6)#此时为全换,因为count未指定参数
m7 = re.sub('-','/','2019-10-8',1)
print(m7)#只替换一次





print('\n第四部分:所执行的替换,基于被替换内容进行改变')
def fun_1(matched):
    #matched就是匹配对象
    s1 = '《hello' + (matched.group('lang'))  + '》'
    #括号内的底层逻辑是: 子串.组(命名为lang的组)
    return s1

s2 = 'world是一本书,python也是一本书'

'''r'(?P<lang>\w+)' 正则表达式。r表示不理会里面的特殊字符,即原始字符串。
并用 ?P<lang>取名为 lang; \w+才是正则表达式内容,\W表示任意字符,+表示
可出现一次到多次 ; \W+表示一个或多个任意字符'''
m8 = re.sub(r'(?P<lang>\w+)',fun_1,s2,flags=re.A)#旗标re.A,表示ASCII字符,不能代表汉字
#也就是把每一段ASCII编码的放进去
'''期间的逻辑是:一个正则表达式子串(用特殊规则在母串中截取的片段),替换
值是一个函数的返回值,表示选取名为'lang'的组中的值,即这个子串。'''
print(m8)







print('\n第五部分:分割 split')

'''re.split(pattern,string,maxsplit=0,flags=0)
 ==>正则,母串,最多分割数,旗标
split:re.split() 基本等同于 string.split(), 返回分割后的列表'''

m9 = re.split('and','apple and banana and orange')
m10 = 'apple and banana and orange'.split('and')
print(m9)
print(m10)
#指定只分割一次
m11 = re.split('and','apple and banana and orange',1)
print(m11)






print('\n第六部分:清除正则表达式缓存(也就是最上面的p),添加转义字符')
re.purge()
m12 = re.escape(r'www.study.cn')
print(m12)

'''re 模块中还包含两个类,一个是正则对象 pattern ,一个是匹配对象 match 
正则表达式对象就是 re.compile 的返回值。该对象的方法与前面 re 模块中的函数大致对应
正则表达式对象的这些方法更加强大,可以额外指定 pos 和 endpos 两个参数,用于指定处理
一个区间的子串。'''






print('\n第七部分:正则表达式的方法来执行匹配')
#编译得到正则表达式对象
q1 = re.compile('fkit')
#调用 match 方法,原本应该从开始位置匹配
n1 = q1.match('www.fkit.org',4)#从4开始
print(n1.span())#(4,8),读取的索引还是相对于母串的索引
n2 = q1.match('www.fkit.org',4,8)#从4开始,从8结束
print(n2.span())





print('\n第八部分:正则表达式中使用组')
m13 = re.search(r'(fkit).(org)',r'www.fkit.org is a good domain')

#调用的简化写法,0表示所有组,group返回一个字符串
print(m13.group(0))# fkit.org
print(m13[0])# fkit.org
print(m13.span(0))# (4,12)

#调用的简化写法,1表示第一组
print(m13.group(1))# fkit
print(m13[1])# fkit
print(m13.span(1))# (4,8)

#调用的简化写法,2表示第二组
print(m13.group(2))# org
print(m13[2])# org
print(m13.span(2))# (9,12)

#返回所有组所匹配的字符串组成的元组
print(m13.groups())# ('fkit', 'org')
'''只要正则表达式能匹配得到结果,不管它是否包含组。group(0)总能获得所匹配的
子串,span(0)总能获得开始结束位置'''


'''如果在正则表达式中为组指定了名字 (?P<名字>一个子串),对比第四部分看'''
print('\n第九部分:获取所有组名字的匹配所组成的字典 groupdict')
#
m14 = re.search(r'(?P<one>fkit).(?P<two>org)',r'www.fkit.org is a good domain')
print(m14.groupdict())#{'one': 'fkit', 'two': 'org'}
#键为 组名 ,值为 子串 。








print('\n第十部分:正则表达式旗标')

# re.A 或re.ASCII: 控制只匹配ASCII值。行内旗标(?a)
# re.DEBUG: 显示编译正则表达式的Debug信息。没有行内旗标
m15 = re.findall('\w+','hello 世界,hello 你好')
print(m15)#['hello', '世界', 'hello', '你好']==>按照字符节点划分
m16 = re.findall('\w+','hello 世界,hello 你好',re.A)
print(m16)#['hello', 'hello']

# re.I 或re.IGNORECASE: 使用正则表达式匹配时,不区分大小写。行内旗标(?i)
#默认区分大小写,所以无匹配
m17 = re.findall('Fkit','fkit is a good domain,FKIT is good')
print(m17)#[]
m18 = re.findall('Fkit','fkit is a good domain,FKIT is good',re.I)
print(m18)#['fkit', 'FKIT']

# re.L 或re.LOCALE: 使用正则表达式不区分大小写,只对bytes模式起作用。行内旗标(?L)

# re.S 或s.DOTALL: 让 . 能匹配包括换行符在内所有字符,如果无此旗标。 . 能匹配不包括换行符的所有字符。行内旗标(?s)
str_1 = '''hellohithanks
hipass'''
m19 = re.findall('hello(.*?)pass',str_1)
m20 = re.findall('hello(.*?)pass',str_1,re.S)
print(m19)#[]
print(m20)#['hithanks\nhi'],结尾一定要跟字符,比如会出现['']

# re.M 或re.MULTILINE: 多行模式, ^ 可以匹配字符串的开头和每行的开头, $ 可以匹配字
#   符串的末尾和每行的末尾(在换行符前后)。行内旗标(?m)
str_2 = '''一个 两个
三个 小朋友
一起 手拉手 玩雪球'''
m21 = re.findall(r'^\w+',str_2,re.M)#匹配行开头
m22 = re.findall(r'\w+$',str_2,re.M)#匹配行结尾
print(m21)#['一个', '三个', '一起']
print(m22)#['两个', '小朋友', '玩雪球']

h1 = re.findall(r'\A\w+',str_2,re.M)#匹配字符串开头
h2 = re.findall(r'\w+\Z',str_2,re.M)#匹配字符串结尾
h3 = re.findall(r'\b\w+',str_2,re.M)#单词的边界
h4 = re.findall(r'\B\w+',str_2,re.M)#非单词的边界
print(h1)#['一个']
print(h2)#['玩雪球']
print(h3)#['一个', '两个', '三个', '小朋友', '一起', '手拉手', '玩雪球']
print(h4)#['个', '个', '个', '朋友', '起', '拉手', '雪球']

# re.U 或re.Unicode: 多余的。

# re.X 或re.VERBOSE: 允许分行书写正则表达式,并可添加注释。行内旗标(?x)
m23_0 = re.compile(r'''2020#年
6#月
18#日''',re.X)
print(m23_0)#re.compile('2020#年\n6#月\n18#日', re.VERBOSE)










print('\n第十一部分:正则表达式中各种字符')

#正则表达式中合法字符
r''' \t制表符
    \n换行符
    \r回车符
    \f换页符
    \a报警符
    \cx:比如Ctrl+V==>\cv'''

#正则表达式中特殊字符
r'''$匹配一行的结尾
    ^匹配一行的开头
    ()标记子表达式(也就是组)的开始位置和结束位置
    []用于确定中括号表达式的开始位置和结束位置
    {}用于标记前面子表达式的出现频度
    *指定前面子表达式可以出现零次或多次
    +指定前面子表达式可以出现一次或多次
    ?指定前面子表达式可以出现零次或一次
    .匹配除\n以外的容易字符
    \转义下一个字符
    |在两项之间任选一项'''

#正则表达式所支持的预定义字符
r'''\d匹配数字
    \s匹配所有空白字符
    \w匹配所有的单词字符
    它们的大写与它们正好相反,\D\S\W'''

m24 = re.findall(r'c\wt','cat cot cet')
print(m24)
m25 = re.findall(r'\d\d\d-\d\d\d\d-\d\d\d','123-1234-1234')
print(m25)

#中括号表达式
r'''[abc],表示枚举abc中任何一个字符
    [a-f],表示a-f范围内任意字符
    [a-cx-z],枚举和范围结合,表示a-c,x-z范围内任意字符
    ^表示非,[^abc]表示除abc外的字符。[^a-f]表示除a-f外所有字符'''

#边界匹配符:看第十部分
r'''^行开头
    $行结尾
    \b单词的边界,即只能匹配单词前后的空白
    \B非单词的边界,即只能匹配不在单词前后的空白
    \A只匹配字符串的开头
    \Z只匹配字符串的结尾,仅用于最后的结尾'''









print('\n第十二部分:子表达式(圆括号表达式)')

#(子表达式): 匹配子表达式,并捕获成一个自动命名的组,后面可通过“\1”引用第一个捕获的组。
str_3='windows 98 publishedin 98'
#后面publishedin连在一起,对应子串里的\W+,空格对应空格,\1表示
m26 = re.search(r'windows (95|98|NT|20) \w+ \1',str_3)
print(m26)

#(?P<组名>子表达式): 捕获成为命名组。用(?P=组名调用)
str_4 = r'<view>这是一个视窗</view>'
m27 = re.search(r'<(?P<V>\w+)>\w+</(?P=V)>',str_4)#如果是findall,就是这个['view']
#findall返回所有满足pattern子串返回的列表。当有子表达式时,返回的是子串的子串形成的列表
print(m27)#<_sre.SRE_Match object; span=(0, 19), match='<view>这是一个视窗</view>'>

#(?:子表达式): 匹配子表达式,但是不捕获
m28 = re.search(r'windows (\d*) \w+',str_3)
print(m28)#<_sre.SRE_Match object; span=(0, 25), match='windows 98 publishedin 98'>

#(?<=子表达式):子表达式必须在匹配内容左侧,但该子表达式不作为匹配的一部分
#(?=子表达式):子表达式必须在匹配内容右侧,但该子表达式不作为匹配的一部分
str_5 = '<html><body><h1>号外!号外!大新闻!</h1></body></html>'
m29 = re.search(r'(?<=<h1>).+?(?=</h1>)',str_5)
print(m29)#<_sre.SRE_Match object; span=(16, 26), match='号外!号外!大新闻!'>

#(?<!子表达式):子表达式必须不在匹配内容左侧,并且该子表达式不作为匹配的一部分
#(?!子表达式):子表达式必须不在匹配内容右侧,并且该子表达式不作为匹配的一部分

#(?#注释的内容):注释组。不影响正则表达式本身
str_6 = 'Www.Baidu.Com'
m30 = re.search(r'[A-Za-z0-9.]{3,}(?#前面子表达式的内容要出现三次及以上)',str_6)
print(m30)#<_sre.SRE_Match object; span=(0, 13), match='Www.Baidu.Com'>

#(?旗标名):旗标组,用于为!!!整个!!!正则表达式添加行内旗标
m31 = re.findall(r'(?i)[A-Z0-9.]+',str_6)#['Www.Baidu.Com']
print(m31)#['Www.Baidu.Com']

#(?旗标名:表达式):只对当前组起作用的旗标
m32 = re.findall(r'(?i:[a-z0-9.]+)Baidu.com',str_6)#['Www.Baidu.Com']
print(m32)#[]

#在旗标前用 - 表示去掉该旗标
m33 = re.search(r'(?-i:[a-z0-9.]+)Baidu.Com',str_6,re.I)
print(m33)#<_sre.SRE_Match object; span=(1, 13), match='ww.Baidu.Com'>









print('\n第十三部分:贪婪模式与勉强模式')
#频度限定,限定前面的子表达式出现的次数
r'''* : 0~N次,等价于 {0,}
    + : 1~N次,等价于 {1,}
    ? : 0~1次,等价于 {0,1}
    {n,m} : n~m次,n 和 m 要为非负整数。
    {n,} : 至少出现n次
    {,m} : 最多出现m次
    {n} : 必须出现n次'''

str_7 = '[email protected].'
#贪婪模式:会尽可能多的匹配,所以匹配到了最末尾的点
m34 = re.search(r'@.+\.',str_7)
print(m34)#<_sre.SRE_Match object; span=(3, 12), match='@efg.com.'>

#勉强模式:尽可能少的匹配。方法是在频度后加 ?
m35 = re.search(r'@.+?\.',str_7)
print(m35)#<_sre.SRE_Match object; span=(3, 8), match='@efg.'>





猜你喜欢

转载自blog.csdn.net/weixin_44925501/article/details/102469506
今日推荐