一、正则表达式的元字符及其意义
. :匹配任意除换行符的单个字符
^:行首锚定
$:行尾锚定
*:匹配任意次,贪婪匹配 等价于{0,}
+:匹配1到多次,贪婪匹配 降价与{1,}
?:匹配0或1次,贪婪匹配 降价与{0,1}
{}:固定次数
{3}:3次
{3,5}:3到5次
:
1.反斜杠后边跟元字符去掉特殊功能
2.反斜杠后边跟普通字符实现特殊功能
d:匹配任何单个十进制数,它相当于类[0-9],匹配一个数字
D:匹配任何单个非数字字符,它相当于[^0-9]
s:匹配任何单个空白字符,它相当于类[ fv]
S:匹配任何单个非空白字符,它相当于[^ fv]
w:匹配任何单个字母数字字符;它相当于类[a-zA-Z0-9]
W:匹配任何单个非字母数字字符,它相当于类[^a-zA-Z0-9]
:匹配一个单词边界,也就是指单词和空格间的位置
3.引用序号对应的字组所匹配的字符串
re.search(r"(alex)(eric)com2", "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("\\", 'abccom') ''' 为了匹配到,又因为为正则元字符,python中也有特殊意义 python编译器拿到4个先转义成2个\,交给正则的编译器 2个再转义成一个无意义的字符\,即可匹配到 ''' print(result) ''' 匹配结果为['\'] 这是python对元字符匹配后的显示方法 ''' result1 = re.findall(r"\", 'abccom') ''' 引入原生字符串,直接将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('blow', 'blow') ''' python中为删除符,有特殊意思,所以直接如上写法无法得到匹配结果 ''' print(result1) #None result2 = re.match('\bblow', 'blow') ''' 给加上转义符,由python转换成 再由正则解释成自己的独特的意义 ''' print(result2.group()) #blow result3 = re.match(r'blow', 'blow') #同理,引入原生字符之后 print(result2.group())
四、正则表达式是的基本方法
1、re.match() 从头匹配
#1、无分组 origin = "hello alex bcd alex lge alex acd 19" r = re.match("hw+", origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组结果 #输出结果:hello () {}
#2、有分组 # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来) origin = "hello alex bcd alex lge alex acd 19" r = re.match("(h)(w+)",origin) r = re.match("(?P<n1>h)(?P<n2>w+)",origin) print(r.group()) # 获取匹配到的所有结果, print(r.groups()) # 获取模型中匹配到的分组结果,在要取的内容加上"()"就可以取出来 print(r.groupdict()) # 获取模型中匹配到的分组结果,在要取的内容前面加上"?P<>" #输出结果:hello ('h', 'ello') {}
2、re.search() 浏览全部字符串,匹配第一个符合规则的字符串
origin = "hello alex bcd alex lge alex acd 19" # 无分组 r = re.search("aw+", origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组结果 #输出结果: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() 将匹配到的所有内容都放置在一个列表中
#1、 n = re.findall("d+wd+","a2b3c4d5") print(n) #结果:['2b3', '4d5'] #匹配成功后,不会在依次向后,跳过匹配到的,然后继续向后匹配
#2、 n = re.findall("","a2b3c4d5") print(n) #结果:['', '', '', '', '', '', '', '', ''] #在匹配到空的东西也会占位置
#无分组 origin = "hello alex bcd alex lge alex acd 19" r = re.findall("aw+", 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) ''' [('a', 'lex'), ('a', 'lex'), ('a', 'lex'), ('a', '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("aw+", origin) print(n) ''' ['hello ', ' bcd ', ' lge ', ' 19'] ''' #有分组 显示分组里的内容 n = re.split("(aw+)",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_-]+)+