Python之正则表达式

一、正则表达式的元字符及其意义

       . :匹配任意除换行符的单个字符

  ^:行首锚定

  $:行尾锚定

  *:匹配任意次,贪婪匹配 等价于{0,}

  +:匹配1到多次,贪婪匹配 降价与{1,}

  ?:匹配0或1次,贪婪匹配 降价与{0,1}

  {}:固定次数

    {3}:3次

    {3,5}:3到5次

  \:

    1.反斜杠后边跟元字符去掉特殊功能

    2.反斜杠后边跟普通字符实现特殊功能

      \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:匹配一个单词边界,也就是指单词和空格间的位置 

    3.引用序号对应的字组所匹配的字符串

re.search(r"(alex)(eric)com\2", "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("\\\\", 'abc\com')
'''
为了匹配到\,又因为\为正则元字符,python中\也有特殊意义
python编译器拿到4个\先转义成2个\,交给正则的编译器
2个\再转义成一个无意义的字符\,即可匹配到\
'''
print(result)
'''
匹配结果为['\\']
这是python对元字符匹配后的显示方法
'''
 
result1 = re.findall(r"\\", 'abc\com')
'''
引入原生字符串,直接将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('\bblow', 'blow')
'''
python中\b为删除符,有特殊意思,所以直接如上写法无法得到匹配结果
'''
print(result1) #None
 
result2 = re.match('\\bblow', 'blow')
'''
给\b加上转义符,由python转换成\b
再由正则解释成自己的独特的意义
'''
print(result2.group()) #blow
 
result3 = re.match(r'\bblow', 'blow')  #同理,引入原生字符之后
print(result2.group())

四、正则表达式是的基本方法

1、re.match()    从头匹配

#1、无分组
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("h\w+", 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("a\w+", 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+\w\d+","a2b3c4d5")
print(n)
#结果:['2b3', '4d5']
#匹配成功后,不会在依次向后,跳过匹配到的,然后继续向后匹配
#2、
n = re.findall("","a2b3c4d5")
print(n)
#结果:['', '', '', '', '', '', '', '', '']
#在匹配到空的东西也会占位置
#无分组
origin = "hello alex bcd alex lge alex acd 19"
r = re.findall("a\w+", 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("a\w+", origin)
print(n)
'''
['hello ', ' bcd ', ' lge ', ' 19']
'''
 
#有分组 显示分组里的内容
n = re.split("(a\w+)",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_-]+)+

 

posted @ 2017-08-25 04:39  爱吃西红柿的猫  阅读(174)  评论(0编辑  收藏  举报