正则表达式学习笔记大全(python)

正则表达式学习笔记(python)

本文系统记录了正则表达式的学习笔记

1 库与函数篇

首先详细介绍的python正则表达式的库re:

match & search & findall

import re

re.match #从开始位置开始匹配,如果开头没有则返回None,顺利匹配则返回匹配值。

re.search #搜索整个字符串,返回符合匹配的值。只返回第一个满足条件的值。

re.findall #搜索整个字符串,返回符合匹配的一个list。返回所有满足条件的值,以列表形式呈现。

# r(raw)用在pattern之前,表示单引号中的字符串为原生字符,不会进行任何转义。
# 由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'/t',等价于'//t')匹配相应的特殊字符。
re.match(r'l','liuyan1').group()  #返回l
re.match(r'y','liuyan1')  #返回None
re.search(r'y','liuyan1').group() #返回y
re.findall(r'yan','liuyan1')       #返回['yan']

re.search(r'[^abc]','aeebdchdcbe').group()  #非a、非b、非c的值。返回'e'
re.findall(r'[^abc]','aeebdchdcbe')         #返回['e', 'e', 'd', 'h', 'd', 'e']

#I     IGNORECASE 忽略大小写区别
#X     VERBOSE    这个选项忽略规则表达式中的空白,并允许使用 ’#’ 来引导一个注释。
re.search(r'[a-z]+','liuyaN1234ab9').group()        #返回'liuya'
re.search(r'[a-z]+','liuyaN1234ab9', re.I).group()  #返回'liuyaN',对大小写不敏感

compile

re.compile   #返回一个Pattern对象,这个pattern可以更便捷的使用上面的函数

s='111,222,aaa,bbb,ccc333,444ddd'
compiled_rule=re.compile(r'/b/d+/b')
compiled_rule.findall(s)  #返回['111', '222']

rcm=re.compile(r'/d+',re.I)

# re 的 match 与 search 函数同 compile 过的 Pattern 对象的 match 与 search 函数的参数是不一样的。
# Pattern 对象的 match 、 search 、findall、finditer函数更为强大,是真正最常用的函数。他们比原来多了指定匹配开始位置和结束位置
#findall ( targetString , startPos ,endPos] )
#finditer ( targetString , startPos ,endPos )
#match ( targetString , startPos ,endPos )
#search ( targetString , startPos ,endPos)

finditer

re.finditer    #返回一个迭代器.finditer 函数和 findall 函数的区别是, findall 返回所有匹配的字符串,并存为一个列表,而 finditer 则并不直接返回这些字符串,而是返回一个迭代器。
s='111 222 333 444'
for i in re.finditer(r'/d+',s):
     print(i.group(),i.span())
## 返回:
#  111 (0, 3)
#  222 (4, 7)
#  333 (8, 11)
#  444 (12, 15)

sub & subn

re.sub       #字符串的替换,返回替换后的字符串
re.subn      #字符串的替换,返回替换后的字符串以及被替换的次数
s=' I have a dog , you have a dog , he have a dog '
re.sub( r'dog' , 'cat' , s )
#返回:' I have a cat , you have a cat , he have a cat '

s=' I have a dog , you have a dog , he have a dog '
re.sub( r'dog' , 'cat' , s , 2)
#返回:' I have a cat , you have a cat , he have a dog '  只替换了前面两个

s=' I have a dog , you have a dog , he have a dog '
re.subn( r'dog' , 'cat' , s )
#返回:(' I have a cat , you have a cat , he have a cat ',3)    返回被替换的次数

split

re.split      #切片函数。使用指定的正则规则在目标字符串中查找匹配的字符串,用它们作为分界,把字符串切片。
s=' I have a dog   ,   you have a dog  ,  he have a dog '
re.split( '/s*,/s*' , s )
#返回: [' I have a dog', 'you have a dog', 'he have a dog ']

2 模式字符串篇

2.1 基本规则

2.1.1 功能字符
# '|'    或规则 '|' 两边的字符串满足其中一个就可以返回
s = 'I have a dog , I have a cat'
re.findall( r'I have a dog|cat',s)  #返回['I have a dog', 'cat']

# '.'    匹配所有字符串,除换行符'\n'。re.S可以让他包含换行符
s='123 \n456 \n789'
re.findall(r'.+',s)          #返回['123 ', '456 ', '789']
re.findall(r'.+' , s , re.S) #返回['123 \n456 \n789']

#‘^’ 和 ’$’ 匹配字符串开头和结尾。注意 ’^’ 不能在‘ [ ] ’中,否则含意就发生变化。在多行模式下,它们可以匹配每一行的行首和行尾。
re.findall(r'^12' , s , re.S)  #返回['12']
2.1.2 集合设定符
# [amk] 匹配 'a','m'或'k'。相当于a|m|k
# [^abc] 匹配除了a,b,c之外的字符

re.findall(r'[英雄]','英雄好汉英雄')            #返回['英', '雄', '英', '雄']
re.findall(r'[^abc]','aeebdchdcbe')         #返回['e', 'e', 'd', 'h', 'd', 'e']
#注意,^需要放在开头。 [a-z^A-Z] 表明的是匹配所有的英文字母和字符 ’^’
re.findall(r'[ab^c]','aeebd^^chdcbe')      #返回['a', 'b', '^', '^', 'c', 'c', 'b']

#[0-9] 匹配任何数字。类似于 [0123456789]
#[a-z] 匹配任何小写字母
#[A-Z] 匹配任何大写字母
#[a-zA-Z0-9] 匹配任何字母及数字
2.1.3 预定义转义字符
# \d   匹配一个数字字符。等价于[0-9]
# \D   匹配一个非数字字符。等价于 [^0-9]。
# \s   匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
# \S   匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
# \w   匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
# \W   匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
# \n   匹配一个换行符,
# \t   匹配一个制表符。
# \A   匹配字符串开头。它和 ’^’ 的区别是, ’/A’ 只匹配整个字符串的开头,即使在 ’M’ 模式下,它也不会匹配其它行的很首。    s= '12 34/n56 78/n90'
# \Z   匹配字符串的结尾。它和 ’$’ 的区别是, ’/Z’ 只匹配整个字符串的结尾,即使在 ’M’ 模式下,它也不会匹配其它各行的行尾。 s= '12 34/n56 78/n90'
# \b   匹配字符边界
# \B   匹配非边界的字符

s ='abc abcde bc bcd'
re.findall(r'\bbc\b', s)    #返回['bc'] ,匹配一个单独的单词 ‘bc’,而当它是其它单词的一部分的时候不匹配
re.findall(r'\sbc\s', s )   #返回[' bc '],配出的字符串中会包含那个分界符。
re.findall( r'\Bbc\w+', s ) #返回['bcde'],匹配包含 ’bc’ 但不以 ’bc’ 为开头的单词。# 成功匹配了 ’abcde’ 中的 ’bcde’ ,而没有匹配 ’bcd’

2.2重复

2.2.1重复多次
#a*  匹配0个或多个的表达式a。
#a+  匹配1个或多个的表达式a。
#a?  匹配0个或1个的表达式a。

re.findall(r'ab*','aababababbb') #返回['a', 'ab', 'ab', 'ab', 'abbb']
re.findall(r'ab+','aababababbb') #返回['ab', 'ab', 'ab', 'abbb']
re.findall(r'ab?','aababababbb') #返回['a', 'ab', 'ab', 'ab', 'ab']
2.2.2精确匹配和最小匹配
# '{m}'      精确匹配 m 次
# '{m,n}'   匹配最少 m 次,最多 n 次。 (n>m)
s = ' 1 22 333 4444 55555 666666 '
re.findall(r'\b\d{3}\b', s)       #返回三位数的数字['333']
re.findall( r'\b\d{2,4}\b', s )  #返回2-4位的数字['22', '333', '4444']
re.findall( r'\b\d{5,}\b', s )    #返回5位及以上的数字['22', '333', '4444']
2.2.2精确匹配和最小匹配
#所谓惰性,就是返回满足条件的最小单元。

# '*?'   重复任意次匹配(0次和n次都可以),但返回的是最少重复的结果
s = 'acbabaccb'
re.findall( r'a.*b', s )   #返回['acbacbaccb'],此时返回a与b之间最多重复次数的那个匹配值
re.findall( r'a.*?b', s )  #返回['acb', 'ab', 'accb'],返回a与b之间最少重复次数的匹配值,一共匹配到三个(也就是a与b之间没有更小单位的可匹配值)
# '+?'   重复任意次匹配(1次和n次都可以),但返回的是最少重复的结果
re.findall( r'a.+?b', s )  #返回['acb','abaccb']
# '??'   重复0次或1次匹配,但返回的是最少重复的结果
re.findall( r'a.??b', s )  #返回['acb', 'ab']
# '{n,m}?'  重复n到m次,但尽可能少重复
re.findall( r'a.{1,2}?b', s )  #返回['acb', 'accb'],为什么不返回'abaccb',因为他超过限定长度
# '{n,}?'    重复n次以上,但尽可能少重复
re.findall( r'a.{1,}?b', s )  #返回['acb', 'abaccb'],为什么会返回'abaccb',因为他是符合条件的最小单元

2.3 组的概念与相关类

#分组就是用一对圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组,也有一种说法称为‘捕获’。
#从正则表达式的左边开始看,看到的第一个左括号“(”表示第一个分组,第二个表示第二个分组,依次类推.
# 需要注意的是,有一个隐含的全局分组(就是0),就是整个正则表达式。
s = "I love javascript and java and scriptscript"
re.search(r'and script',s).group(0)  #返回'and script',这个常规查找一个字符串
#现在对他进行一个分组
re.search(r'(and )(script)',s).group(0)   #返回'and script',第0组返回全局分组
re.search(r'(and )(script)',s).group(1)   #返回'and ',返回第一个分组
re.search(r'(and )(script)',s).group(2)   #返回'script',返回第二个分组
#分组以后可以对分组内容进行重复计算
re.search(r'(and )(script)+',s).group(0)    #返回'and scriptscript',在全局分组中,响应了+
re.search(r'(and )(script)+',s).group(1)    #返回'and ',返回第一个分组
re.search(r'(and )(script)+',s).group(2)    #返回'script',返回第二个分组
#findall返回内容会有所不同,他先匹配出全局分组,然后从全局分组提取子分组展示出来
s = "I love javascript and scriptscript and scriptscript"
re.findall(r'(and )(script)+',s)   #返回[('and ', 'script'), ('and ', 'script')],现在能匹配到两段,把两段都回传,并把其他子分组提取出来
# 有些时候分组太多,我们可以命名分组
# (?P<name>正则表达式)   name是一个合法的标识符
re.search(r'(and )(?P<sp>script)',s).group('sp')  #返回'script',命名以后就可以用名字来进行索引
#使用compile对象可以查询分组索引
aa=re.compile(r'(and )(?P<sp>script)')
aa.groupindex  #返回mappingproxy({'sp': 2})
# 无捕获数组,我们希望匹配,但是无需捕获
# (?:exp) 匹配exp,不捕获匹配的文本
re.search(r'(and )(?:script)',s).group(0)  #返回'and script'
re.search(r'(and )(?:script)',s).group(1)  #返回'and '
re.search(r'(and )(?:script)',s).group(2)  #报错无返回
re.findall(r'(and )(?:script)',s)          #返回['and '],没有返回script
#当你只是希望利用分组来进行重复计数,但不需要返回指定分组的时候,可以使用无捕获数组,减少内存压力
re.search(r'and (?:script)+',s).group(0)   #返回'and scriptscript'
# 编译指定选项组
# Python 的正则式可以指定一些选项,这个选项可以写在 findall 或 compile 的参数中,也可以写在正则式里,成为正则式的一部分。
# 编译选项 ’i’ 等价于 IGNORECASE ,L 等价于 LOCAL ,m 等价于 MULTILINE , s 等价于 DOTALL , u 等价于 UNICODE , x 等价于 VERBOSE
#(?imx: exp)  	在括号中使用i, m, 或 x 可选标志,只影响组内
#(?-imx: re)    在括号中不使用i, m, 或 x 可选标志
# 注释组'(?# exp)' exp为注释内容
#Python 允许你在正则表达式中写入注释,在 (?#'exp') 之间的内容将被忽略

3 compile的拓展内容

#compile以后获得一个编译的pattern对象

#flags       查询编译时的选项
#pattern 查询编译时的规则
#groupindex 规则里的组
p = re.compile(r'(?P<word>/b[a-z]+/b)|(?P<num>/b/d+/b)|(?P<id>/b[a-z_]+/w*/b)', re.I )
p.flags    #返回2
p.pattern  #返回'(?P<word>//b[a-z]+//b)|(?P<num>//b//d+//b)|(?P<id>//b[a-z_]+//w*//b)'
p.groupindex #返回{'num': 2, 'word': 1, 'id': 3}

content='xshfjdshfks'
m1 = p.match(content,3)
m1.group()   #返回匹配结果
m1.group(0)  #返回匹配的全局分组
m1.groupdict()       #返回以组名为 key ,匹配的内容为 values 的字典
m1.span()    #返回匹配范围
m1.start()   #返回开始下标
m1.end()     #返回结束下标
m1.expand(template)  #将匹配到的分组代入template中然后返回。template中可以使用\id或\g<id>、\g<name>引用分组
m1.expand(r'name is /g<1> , age is /g<age> , tel is /3')   #返回'name is Tom , age is 24 , tel is 88888888'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值