正则表达式

正则表达式

一.认识正则表达式

  正则表达式是什么 ?

    正则表达式是一门单独的语音,不仅属python,很多语言都可以调用它,它自成体系

  正则表达式有什么用呢?

    首先我们看一下python自带的字符串的一些功能方法

str1 = "abcdefg"
result1 = str1.find("b")
result2 = str1.find("bc")
result3 = str1.split("b")
result4 = str1.replace("ab", "AB")
print("b的位置是:%s" % result1)
print("bc的位置是:%s" % result2)
print("字符串以b分割成:%s" % result3)
print("字符串替换后的结果是:%s" % result4)

  我们可以观察得到,无论是查找,分割,或者替换都需要明确具体的元素

  而正则表达式可以给出一个pattern,符合要求的可以有很多,不仅仅局限唯一

 

二.正则表达式的元字符及其意义

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

  ^:行首锚定

  $:行尾锚定

  *:匹配任意次,贪婪匹配 等价于{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()

import re

# re.match()  从头匹配,返回一个对象
# 无分组匹配
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("hw+", origin)
print(r.group())  # 获取匹配到的所有结果(无分组时,只有group有意义)
print(r.groups())  # 获取模型中匹配到的分组结果,无意义
print(r.groupdict())  # 获取模型中匹配到的分组中所有执行了key的组

'''
hello
()
{}
'''

# 有分组匹配
r = re.match("(h)(w+)", origin)
print(r.group())      # 获取匹配到的所有结果
print(r.groups())     # 获取模型中匹配到的分组结果,分组才有意义
r = re.match("(?P<n1>h)(?P<n2>w+)", origin)
print(r.groupdict())  # 获取模型中匹配到的分组中所有执行了key的组,分组才有意义

'''
hello
('h', 'ello')
{'n1': 'h', 'n2': 'ello'}
'''

 

2.re.search()

import re
#re.search() 浏览全部字符串,匹配第一个合法的字符串,返回一个对象
#无分组匹配
origin = "hello alex bcd alex lge alex acd 19"
r = re.search("aw+", origin)
print(r.group())     #获取匹配到的所有结果(无分组时,只有group有意义)
print(r.groups())    #获取模型中匹配到的分组结果,无意义
print(r.groupdict()) #获取模型中匹配到的分组中所有执行了key的组
'''
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()

import re
origin = "a2b3c4d5"
result = re.findall("d+wd+", origin)
print(result)
'''
['2b3', '4d5']
'''
#无分组
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)
'''
['lex', 'lex', 'lex', '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_-]+)+

  

七.课后作业,计算器开发


re.split("([^()]+)", expression)    ()有特殊意义,表示分组,[]里面的符号都没有特殊意义,不需要转义
		
def f1(ex):
  pass
origin = "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) " while True: result = re.split("(([^()]+))",origin,1) if len(result) == 3: #before = result[0] #content = result[1] #after = result[2]
before,content,after = result r = f1(content) new_str = before + r + after origin = new_str else: final = f1(result[0]) print(final) print(origin) break

计算1*2+3*4+5*6+..+99*100的值

# 1*2+3*4+5*6+7*8+9*10

import re


def f1(arg):
    arg1, arg2 = arg.split('*')
    r = (int(arg1)) * (int(arg2))
    return str(r)


def seq(arg1, arg2):
    seq = ''
    for i in range(arg1, arg2):
        if i % 2 == 0 and i != arg2 - 1:
            seq = seq + str(i) + '+'
        elif i % 2 != 0:
            seq = seq + str(i) + '*'
        else:
            seq = seq + str(i)

    return seq


def add1(data):
    summ = 0
    ret = data.split('+')
    for i in ret:
        summ = int(i) + summ

    return summ


if __name__ == '__main__':
    a = int(input("输入一下格式:1*2+3*4+5*6+7*8+9*10,首:"))
    b = int(input("输入一下格式:1*2+3*4+5*6+7*8+9*10,尾:"))
    seq1 = seq(a, b + 1)
    while True:
        result = re.split(r'(d{1,2}*d{1,2})', seq1, 1)
        if len(result) == 3:
            # print(result)
            before = result[0]
            content = result[1]
            after = result[2]
            r = f1(content)
            new_str = before + r + after
            seq1 = new_str
        else:
            # print(result)
            # print(seq1)
            break
    result = add1(seq1)
    print(result)
原文地址:https://www.cnblogs.com/wuwen19940508/p/6876246.html