装饰器和正则表达式

装饰器

装饰器的原则:

  1. 开放封闭原则 装饰器 用来装饰函数,装饰器在让调用方式不变的情况下,扩充功能
  2. 不修改原函数的代码可以让函数在执行前或执行后再执行其它的操作
  3. 只要函数应用上装饰器,那么函数就会被重新定义,重新定义为装饰器的 内层函数

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。 

案列如下:案列一

#/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
开放封闭原则 装饰器 用来装饰函数,装饰器在让调用方式不变的情况下,扩充功能
不修改原函数的代码可以让函数在执行前或执行后再执行其它的操作
执行步骤
1、python的执行原则是从上到下依次执行
第一步:执行 def  outer 先把outer 函数放入内存,先不执行
第二步:执行到@outer时 会把它下面的函数名f1当作参数传递给outer函数 并执行outer函数 即: outer(func) ==> outer(f1) 返回值为 return inner(inner函数名)
第三步:outer函数的返回值 inner 会重新赋值给 f1  即 f1 =outer
第四步:执行 inner() 函数
第五步:re = func()   func函数名 = f1 函数 名  执行 func()函数相当于 执行  f1()函数
第六步:return   re 时由inner()函数调用的
1、到	@outer 执行outer(@后面的函数)函数。并且将其下面的函数名当参数(把@outer下面的f1当作参数传递给outer函数 也就是 f1 = func)
2、将outer的返回值重新赋值给F1 f1 = outer的返回值
新f1函数 = inner

"""
def outer(func):
    def inner():
        print('start')
        print('start')
        re = func()
        print('end')
        print('end')
        return re
    return inner
@outer
def f1():
    print('f1')
    return '原始'
result = f1()
print(result)

案列二:

#/usr/bin/env python
# -*- coding: UTF-8 -*-
#以下两种方法输出的结果集是一样的
print('++++++++++++++++方法一++++++++++++++')
def outer(func):
    # func = #原来的f1函数
    def inner():
        print('hello')
        print('hello')
        print('hello')
        # 源f1函数
        r = func()  # r= None
        print('end')
        print('end')
        print('end')
        return r
    return inner
@outer
def f1():
    print('f1')
    return 'ooo'
result = f1()
print(result)

print('+++++++++++++方法二+++++++++++++')
def outer(func):
    # func = #原来的f1函数
    def inner():
        print('hello')
        print('hello')
        print('hello')
        # 源f1函数
        r = func()  # r= None
        print('end')
        print('end')
        print('end')
        return r
    return inner
# @outer
def f1():
    print('f1')
    return 'ooo'
# f1()
f1 = outer(f1) #= > @outer
result = f1()
print(result)

 函数继承一个装饰器

案列一

# /usr/bin/env python
# -*- coding: UTF-8 -*-
#默认情况下打印index2函数的内存地址
def index2():
    pass
print(index2)
print('+++++++++++++++++++')
"""
1、index 作为参数传递给outer 即执行   outer(func) 相当于执行 outer(index)
2、并把outer(func) 返回值 AA  重新赋值给index   即 原始print(index) 函数的内存地址就等于 AA
"""
def outer(func):
    return 'AA'
@outer
def index():
    return 'PP'
print(index)

案列二:

#/usr/bin/env python
# -*- coding: UTF-8 -*-
#输出结果为123  此时 index 等于outer的返回值 也就是等于inner函数名
"""
1、在执行@outer 时 会把index作为参数传递给outer函数 即outer(func) 相当于 outer(index)
2、outer(func)的返回值 为 inner
3、会把返回结果重新赋值给 index  即
 def inner():
        print('123')
        相当于
def index():
    # 非常复杂的功能
    return True
4、  ret2 = index() 相当于执行     ret2 = inner()
5、因
 def inner():
        print('123')
执行结果为 123 没有返回值 所以 ret2 = index() 的结果为123  ,返回值为None
"""
def outer(func):
    def inner():
        print('123')
    return inner
@outer
def index():
    # 非常复杂的功能
    return True
ret2 = index()
print(ret2)
print('+++++++++++++++++++')
def index():
    print('123')
    # 非常复杂的功能
    return True
ret = index()
print(ret)


# # ================
#/usr/bin/env python
# -*- coding: UTF-8 -*-
#输出结果为123  此时 index 等于outer的返回值 也就是等于inner函数名
def outer(func):
    def inner():
        print('123')
        func()
        print('456')
    return inner
@outer
def index():
    # 非常复杂的功能
    print('非常复杂的功能')
index()

装饰器加参数

#只要函数应用上装饰器,那么函数就会被重新定义,重新定义为装饰器的 内层函数

#/usr/bin/env python
# -*- coding: UTF-8 -*-
#输出结果为123  此时 index 等于outer的返回值 也就是等于inner函数名
def outer(func):
    def inner(a1,a2):
        print('123')
        ret = func(a1,a2)
        print('456')
        return ret
    return inner
@outer
def index(a1,a2):
    # 非常复杂的功能
    print('非常复杂的功能')
    return a1 + a2
index(1,2)

万能参数

#/usr/bin/env python
# -*- coding: UTF-8 -*-
def f1(*args,**kwargs):
    print(args)
    print(kwargs)
f1(1,2,3,4,5,k1= 'jack')

 

#/usr/bin/env python
# -*- coding: UTF-8 -*-
#都会先执行inner函数,再执行原函数
def outer(func):
    def inner(*args,**kwargs):
        print('123')
        ret = func(*args,*kwargs)
        print('456')
        return ret
    return inner
@outer
#两个参数的
def index(a1,a2):
    # 非常复杂的功能
    print('非常复杂的功能')
    return a1 + a2
index(1,2)
print('+++++++++一个参数的+++++++++++++++')
@outer
#一个参数的
def f2(arg):
    print('f2')
f2(123)
print('+++++++++++++三个参数+++++++++')
@outer
#个参数的
def f3(a1,a2,a3):
    print('f3')
f3(1,2,3,)

 一个函数继承两个装饰器

#/usr/bin/env python
# -*- coding: UTF-8 -*-
#一个函数应用两个装饰器
def outer_0(func):
    def inner(*args,**kwargs):
        print('3.5')
        ret = func(*args,*kwargs)
        return ret
    return inner

def outer(func):
    def inner(*args,**kwargs):
        print('123')
        ret = func(*args,*kwargs)
        print('456')
        return ret
    return inner
@outer_0
@outer
#两个参数的
def index(a1,a2):
    # 非常复杂的功能
    print('非常复杂的功能')
    return a1 + a2
index(1,2) 

 

装饰器的演变过程

装饰器原则

  • 不修改函数的调用方式
  • 不修改函数的源代码
  • 给函数增加新的功能

 

#!/usr/bin/env python
#-*- coding:utf-8 -*-

#虽然增加了新功能,但是修改函数了调用方式
# 高阶函数定义:
# 1.函数接收的参数是一个函数名
# 2.函数的返回值是一个函数名
# 3.满足上述条件任意一个,都可称之为高阶函数
import time
#原函数
def foo():
    time.sleep(0.3)
    print('from foo')
def test(foo):
    start_time = time.time()
    foo()
    end_time = time.time()
    print('函数的执行时间是%s' %(end_time - start_time))
#调用原函数的方式
foo()
#修改后,修改了函数的调用方式
test(foo)
print('+++++++++++++++++++++++++++++++++++++++++++++++++++++')

#虽然没有修改函数的调用方式,但是没有增加新的功能
import time
def foo2():
    time.sleep(0.3)
    print('from foo')
def test2(func):
    return func

# obj = test(foo)
# obj()
foo2 = test2(foo2)
foo2()

print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
#函数的调用方式没有变,为函数也增加了新的功能。但是多执行了一次
import  time
def foo3():
    time.sleep(0.3)
    print('from foo3')

#函数的调用方式没有变,为函数也增加了新的功能。但是多执行了一次
def test3(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print('函数运行时间是%s' %(end_time - start_time))
    return func
foo3 = test3(foo3)
foo3()

#没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
def test3(func):
    start_time = time.time()
    return func
    end_time = time.time()
    print('函数运行时间是%s' %(end_time - start_time))
foo3 = test3(foo3)
foo3()
装饰器演变过程代码

 

下面的函数里装饰器   @timmer 相当于  test = timmer(test)  案列如下:、

装饰器解说版本:test = timmer(test)  

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import  time
def timmer(func):
    def wrapper():
        print('开始准备执行函数了')
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数执行完毕')
        print('函数的执行时间是%s' %(end_time - start_time))
    return wrapper

def test():
    time.sleep(0.3)
    print('from test')
test = timmer(test)
test()

 装饰器版本  此版本装饰器没有加返回值 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import  time
def timmer(func):
    def wrapper():
        print('开始准备执行函数了')
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数执行完毕')
        print('函数的执行时间是%s' %(end_time - start_time))
    return wrapper
@timmer  # @timmer 相当于test = timmer(test)
def test():
    time.sleep(0.3)
    print('from test')
test()

 装饰器版本  加上函数返回值的装饰器 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
def timmer(func):
    def wrapper():
        print('函数准备开始执行了')
        start_time = time.time()
        res = func()
        end_time = time.time()
        print('函数执行完毕')
        print('函数执行时间是%s' %(end_time - start_time))
        return res
    return wrapper
@timmer  #相当于test = timmer(test)
def test():
    time.sleep(0.3)
    print('from test')
    return ('这是test的返回值')
# test = timmer(test)
obj = test()
print(obj)

 装饰器版本  加上函数返回值、函数入参参数 的装饰器 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        print('函数开始执行了')
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print('函数执行完毕')
        print('函数的执行时间是%s' %(end_time - start_time))
        return res
    return wrapper
@timmer #test = timmer(test)  @timmer相当于 #test = timmer(test)
def test(name,age):
    time.sleep(0.3)
    print('my name is %s,age is %s'%(name,age))
    return ('我是test函数的返回值')
# test = timmer(test)
obj = test('alex',20)
print(obj)

装饰器版本  给多个函数增加验证登录功能

1、多次验证

#!/usr/bin/env python
#-*- coding:utf-8 -*-
def timmer(func):
    def wrapper(*args,**kwargs):
        username = input('请输入用户名:').strip()
        paswd = input('请输入密码:').strip()
        if username == 'alex' and paswd == '123' :
            res = func(*args,**kwargs)
            return res
        else:
            print('用户名或者密码错误')
    return wrapper

@timmer  #相当于home = timmer(home)
def home(name):
    print('欢迎%s回家' %name)
    return '%s 成功回家' %name

@timmer  #相当于buy= timmer(buy)
def buy(name):
    print('%s买回来的东西有水果,饮料,鸡蛋' %name)
    return '%s 买的水果很好吃' %name
@timmer #相当于chi= timmer(chi)
def chi():
    print('我喜欢吃')

obj1 = home('alex')
print(obj1)
obj2 = buy('jack')
print(obj2)
obj3 = chi()
print(obj3)
给多个函数增加验证登录功能

2、给多个函数增加验证,只验证一次

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @timmer  #相当于home = timmer(home)
login_dict = {'username':None,'login':False}
def timmer(func):
    def wrapper(*args,**kwargs):
        if login_dict['username'] and login_dict['login']:
            res = func(*args,**kwargs)
            return res
        username = input('请输入用户名:').strip()
        paswd = input('请输入密码').strip()
        if username == 'alex' and paswd == '123':
            login_dict['username'] = True
            login_dict['login'] = True
            res = func(*args,**kwargs)
            return res
    return wrapper

@timmer #相当于home = timmer(home)
def home(name):
    print('欢迎%s回家' %name)
    return '%s 成功回家' %name
# home = timmer(home)
# home()

@timmer  #相当于buy= timmer(buy)
def buy(name):
    print('%s买回来的东西有水果,饮料,鸡蛋' %name)
    return '%s 买的水果很好吃' %name
@timmer #相当于chi= timmer(chi)
def chi():
    print('我喜欢吃')

obj1 = home('alex')
print(obj1)
obj2 = buy('jack')
print(obj2)
obj3 = chi()
print(obj3)
给多个函数增加验证,只验证一次
#!/usr/bin/env python
#-*- coding:utf-8 -*-
user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]
current_dic={'username':None,'login':False}


def auth_func(func):
    def wrapper(*args,**kwargs):
        if current_dic['username'] and current_dic['login']:
            res = func(*args, **kwargs)
            return res
        username=input('用户名:').strip()
        passwd=input('密码:').strip()
        # username = 'ale3x'
        # passwd = '123'
        for user_dic in user_list:
            if username == user_dic['name'] and passwd == user_dic['passwd']:
                current_dic['username']=username
                current_dic['login']=True
                res = func(*args, **kwargs)
                return res
        else:
            print('用户名或者密码错误')

    return wrapper

@auth_func #index = auth_func(index)
def index():
    print('欢迎来到京东主页')

@auth_func
def home(name):
    print('欢迎回家%s' %name)

@auth_func
def shopping_car(name):
    print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))

print('before-->',current_dic)
index()
print('after--->',current_dic)
home('产品经理')
shopping_car('产品经理')
案列2

3、给多个函数增加验证,同时是指定用户和密码

#!/usr/bin/env python
#-*- coding:utf-8 -*-
user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]
login_dict ={'username':False,'login':False}
def timmer(func):
    def wrapper(*args,**kwargs):
        if login_dict['username'] and login_dict['login']:
            res = func(*args,**kwargs)
            return res
        username = input('请输入用户名:').strip()
        paswd = input('请输入密码:').strip()
        for x in user_list:
            if username == x['name'] and paswd == x['passwd']:
                login_dict['username'] = True
                login_dict['login'] = True
                res = func(*args,**kwargs)
                return res
        print('用户名或者密码不对,或者此用户没有进行注册')
    return wrapper

@timmer  #相当于home = timmer(home)
def home(name):
    print('欢迎%s回家' %name)
    return '%s 成功回家' %name
# home = timmer(home)
# home()
@timmer  #相当于buy= timmer(buy)
def buy(name):
    print('%s买回来的东西有水果,饮料,鸡蛋' %name)
    return '%s 买的水果很好吃' %name
@timmer #相当于chi= timmer(chi)
def chi():
    print('我喜欢吃')

print('----->之前',login_dict)
obj1 = home('alex')
print(obj1)
print('---->之后',login_dict)

print('----->之前',login_dict)
obj2 = buy('jack')
print(obj2)
print('---->之后',login_dict)

print('----->之前',login_dict)
obj3 = chi()
print(obj3)
print('---->之后',login_dict)

 4、装饰器也增加参数 

我的版本

#!/usr/bin/env python
# -*- coding:utf-8 -*-
user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]
login_dict = {'username':False,'login':False}
def auth(auth_type = 'filedb'):
    def timmer(func):
        def wrapper(*args,**kwargs):
            if auth_type == 'filedb':
                print('认证方式是:%s' %auth_type)
                if login_dict['username'] == True and  login_dict['login'] == True:
                    res = func(*args,**kwargs)
                    return res
                username = input('请输入用户名:')
                paswd = input('请输入密码:')
                for x in user_list :
                    if username == x['name'] and paswd == x['passwd'] :
                        login_dict['username'] = True
                        login_dict['login']= True
                        res = func(*args,**kwargs)
                        return res
                else:
                    print('用户名或者密码错误,或者此用户还没有被注册')
            elif auth_type == 'lamdb':
                print('认证方式是%s' %auth_type)
                res = func(*args,**kwargs)
                return  res
            else:
                print('我也不知道是什么认证方式')
                res = func(*args,**kwargs)
                return res
        return wrapper
    return timmer

@auth(auth_type = 'filedb')
def home(name):
    print('欢迎%s回家' %name)
    return '%s 成功回家' %name
# home = timmer(home)
# obj = home('alex')
# print(obj)
@auth(auth_type = 'lamdb')
def buy(name):
    print('%s买回来的东西有水果,饮料,鸡蛋' %name)
    return '%s 买的水果很好吃' %name
@auth(auth_type = 'xxx')
def chi():
    print('我喜欢吃')

print('---------->before',login_dict)
obj1 = home('jack')
print(obj1)
print('---------->before>after',login_dict)
#
print('---------->before',login_dict)
obj2 = buy('wusir')
print(obj2)
print('---------->before>after',login_dict)

print('---------->before',login_dict)
obj3 = chi()
print(obj3)
print('---------->before>after',login_dict)
装饰器增加参数

老师的版本

#!/usr/bin/env python
# -*- coding:utf-8 -*-

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]
current_dic={'username':None,'login':False}

def auth(auth_type='filedb'):
    def auth_func(func):
        def wrapper(*args,**kwargs):
            print('认证类型是',auth_type)
            if auth_type == 'filedb':
                if current_dic['username'] and current_dic['login']:
                    res = func(*args, **kwargs)
                    return res
                username=input('用户名:').strip()
                passwd=input('密码:').strip()
                for user_dic in user_list:
                    if username == user_dic['name'] and passwd == user_dic['passwd']:
                        current_dic['username']=username
                        current_dic['login']=True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print('用户名或者密码错误')
            elif auth_type == 'ldap':
                print('鬼才特么会玩')
                res = func(*args, **kwargs)
                return res
            else:
                print('鬼才知道你用的什么认证方式')
                res = func(*args, **kwargs)
                return res

        return wrapper
    return auth_func

@auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
def index():
    print('欢迎来到京东主页')

@auth(auth_type='ldap')
def home(name):
    print('欢迎回家%s' %name)
#
@auth(auth_type='sssssss')
def shopping_car(name):
    print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))

# print('before-->',current_dic)
# index()
# print('after--->',current_dic)
# home('产品经理')
shopping_car('产品经理')

  

  

 

正则表达式

 

一、简介

正则表达式本身是一种小型的、高度专业化的编程语言,而在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行。

二、正则表达式中常用的字符含义

1、普通字符和11个元字符:

普通字符
匹配自身
abc
abc
.
匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符
a.c
abc
\
转义字符,使后一个字符改变原来的意思
a\.c;a\\c
a.c;a\c
*
匹配前一个字符0或多次
abc*
ab;abccc
+
匹配前一个字符1次或无限次
abc+
abc;abccc
?
匹配一个字符0次或1次
abc?
ab;abc
^
匹配字符串开头。在多行模式中匹配每一行的开头 ^abc
abc
$
匹配字符串末尾,在多行模式中匹配每一行的末尾 abc$
abc
| 或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式
abc|def
abc
def
{} {m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次
ab{1,2}c
abc
abbc
[]
字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。
所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义恢复特殊字符的特殊含义。
a[bcd]e
abe
ace
ade
 
()
被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.
分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。
(abc){2}
a(123|456)c
abcabc
a456c

这里需要强调一下反斜杠\的作用:

    • 反斜杠后边跟元字符去除特殊功能;(即将特殊字符转义成普通字符)
    • 反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
    • 引用序号对应的字组所匹配的字符串。
a=re.search(r'(tina)(fei)haha\2','tinafeihahafei tinafeihahatina').group()
print(a)
结果:
tinafeihahafei

 

2、预定义字符集(可以写在字符集[...]中) 

 

\d
数字:[0-9]
a\bc
a1c
\D
非数字:[^\d]
a\Dc
abc
\s
匹配任何空白字符:[<空格>\t\r\n\f\v]
a\sc
a c
\S 非空白字符:[^\s]
a\Sc
abc
\w
匹配包括下划线在内的任何字字符:[A-Za-z0-9_]
a\wc
abc
\W
匹配非字母字符,即匹配特殊字符
a\Wc
a c
\A
仅匹配字符串开头,同^ \Aabc
abc
\Z
仅匹配字符串结尾,同$
abc\Z
abc
\b
匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 \babc\b
a\b!bc
空格abc空格
a!bc
\B
[^\b]
a\Bbc
abc

 

 

这里需要强调一下\b的单词边界的理解:w = re.findall('\btina','tian tinaaaa')
print(w)
s = re.findall(r'\btina','tian tinaaaa')
print(s)
v = re.findall(r'\btina','tian#tinaaaa')
print(v)
a = re.findall(r'\btina\b','tian#tina@aaa')
print(a)
执行结果如下:
[]
['tina']
['tina']
['tina']

 

3、特殊分组用法:

(?P<name>)
分组,除了原有的编号外再指定一个额外的别名 (?P<id>abc){2}
abcabc
(?P=name)
引用别名为<name>的分组匹配到字符串 (?P<id>\d)abc(?P=id)
1abc1
5abc5
\<number>
引用编号为<number>的分组匹配到字符串 (\d)abc\1
1abc1
5abc5

 

 

三、re模块中常用功能函数

1、compile()

编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率。)

格式:

re.compile(pattern,flags=0)

pattern: 编译时用的表达式字符串。

flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:

标志
含义
re.S(DOTALL)
使.匹配包括换行在内的所有字符
re.I(IGNORECASE)
使匹配对大小写不敏感
re.L(LOCALE)
做本地化识别(locale-aware)匹配,法语等
re.M(MULTILINE)
多行匹配,影响^和$
re.X(VERBOSE)
该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
re.U
根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B

 

import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))   #查找所有包含'oo'的单词
执行结果如下:
['good', 'cool']

2、match()

决定RE是否在字符串刚开始的位置匹配。//注:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'

格式:

re.match(pattern, string, flags=0)

print(re.match('com','comwww.runcomoob').group())
print(re.match('com','Comwww.runcomoob',re.I).group())
执行结果如下:
com
com

 

3、search()

 格式:

re.search(pattern, string, flags=0)

re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None

print(re.search('\dcom','www.4comrunoob.5com').group())
执行结果如下:
4com

*注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:

  • group() 返回被 RE 匹配的字符串
  • start() 返回匹配开始的位置
  • end() 返回匹配结束的位置
  • span() 返回一个元组包含匹配 (开始,结束) 的位置
  • group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。

a. group()返回re整体匹配的字符串,
b. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
c.groups()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。 

import re
a = "123abc456"
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))   #123abc456,返回整体
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))   #123
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))   #abc
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))   #456###group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。###

4、findall()

re.findall遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。

 格式:

re.findall(pattern, string, flags=0)

p = re.compile(r'\d+')
print(p.findall('o1n2m3k4'))
执行结果如下:
['1', '2', '3', '4']
 
import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))
print(re.findall(r'(\w)*oo(\w)',tt))#()表示子表达式 
执行结果如下:
['good', 'cool']
[('g', 'd'), ('c', 'l')]

5、finditer()

 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回。

格式:

re.finditer(pattern, string, flags=0)

iter = re.finditer(r'\d+','12 drumm44ers drumming, 11 ... 10 ...')
for i in iter:
    print(i)
    print(i.group())
    print(i.span())
执行结果如下:
<_sre.SRE_Match object; span=(0, 2), match='12'>
(0, 2)
<_sre.SRE_Match object; span=(8, 10), match='44'>
(8, 10)
<_sre.SRE_Match object; span=(24, 26), match='11'>
(24, 26)
<_sre.SRE_Match object; span=(31, 33), match='10'>
(31, 33)

 

6、split()

按照能够匹配的子串将string分割后返回列表。

可以使用re.split来分割字符串,如:re.split(r'\s+', text);将字符串按空格分割成一个单词列表。

格式:

re.split(pattern, string[, maxsplit])

maxsplit用于指定最大分割次数,不指定将全部分割。

print(re.split('\d+','one1two2three3four4five5'))
执行结果如下:
['one', 'two', 'three', 'four', 'five', '']

 

7、sub()

使用re替换string中每一个匹配的子串后返回替换后的字符串。

格式:

re.sub(pattern, repl, string, count)

import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))
执行结果如下:
JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...
其中第二个函数是替换后的字符串;本例中为'-'
第四个参数指替换个数。默认为0,表示每个匹配项都替换。

re.sub还允许使用函数对匹配项的替换进行复杂的处理。

如:re.sub(r'\s', lambda m: '[' + m.group(0) + ']', text, 0);将字符串中的空格' '替换为'[ ]'。

import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', lambda m:'['+m.group(0)+']', text,0))
执行结果如下:
JGood[ ]is[ ]a[ ]handsome[ ]boy,[ ]he[ ]is[ ]cool,[ ]clever,[ ]and[ ]so[ ]on...

8、subn()

 返回替换次数

格式:

subn(pattern, repl, string, count=0, flags=0)

print(re.subn('[1-2]','A','123456abcdef'))
print(re.sub("g.t","have",'I get A,  I got B ,I gut C'))
print(re.subn("g.t","have",'I get A,  I got B ,I gut C'))
执行结果如下:
('AA3456abcdef', 2)
I have A,  I have B ,I have C
('I have A,  I have B ,I have C', 3)

 

四、一些注意点

1、re.match与re.search与re.findall的区别:

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

a=re.search('[\d]',"abc33").group()
print(a)
p=re.match('[\d]',"abc33")
print(p)
b=re.findall('[\d]',"abc33")
print(b)
执行结果:
None
['3', '3']

2、贪婪匹配与非贪婪匹配

*?,+?,??,{m,n}?    前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

a = re.findall(r"a(\d+?)",'a23b')
print(a)
b = re.findall(r"a(\d+)",'a23b')
print(b)
执行结果:
['2']
['23']

a = re.match('<(.*)>','<H1>title<H1>').group()
print(a)
b = re.match('<(.*?)>','<H1>title<H1>').group()
print(b)
执行结果:
<H1>title<H1>
<H1>

  

a = re.findall(r"a(\d+)b",'a3333b')
print(a)
b = re.findall(r"a(\d+?)b",'a3333b')
print(b)
执行结果如下:
['3333']
['3333']
#######################
这里需要注意的是如果前后均有限定条件的时候,就不存在什么贪婪模式了,非匹配模式失效。

 

3、用flags时遇到的小坑

print(re.split('a','1A1a2A3',re.I))#输出结果并未能区分大小写
这是因为re.split(pattern,string,maxsplit,flags)默认是四个参数,当我们传入的三个参数的时候,系统会默认re.I是第三个参数,所以就没起作用。如果想让这里的re.I起作用,
写成flags=re.I即可。 

五、正则的小实践

1、匹配电话号码

p = re.compile(r'\d{3}-\d{6}')
print(p.findall('010-628888'))

2、匹配IP

re.search(r"(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]\.)","192.168.1.1")

 

案列 

1、 find 和split 
import re
v_str = 'abcd'
print(v_str.find('b'))
print(v_str.find('a'))
print(v_str.find('cd'))
result = v_str.split('b')
print(result)
print(v_str.replace('bc','ff'))



2、re.findall ('alex','yuanalexadfdwupeiqi')   

>>> import re
>>> re.findall ('alex','yuanalexadfdwupeiqi')
['alex']
>>> re.findall ('alex','yuanalewadfdwupeiqi')
[]
>>> re.findall ('alex','yuanalexadfdwupeiqialex')
['alex', 'alex']
>>>

.代表一个字符
>>> re.findall('alex.w','adfalexaw')
['alexaw']
>>> re.findall('alex.w','adfalexadw')
[]
>>>



^是控制开头的
>>> re.findall('^alex','adfalexadw')
[]
>>> re.findall('^alex','adf^alexadw')
[]
>>> re.findall('^alex','alexadf^alexadw')
['alex']
>>> re.findall('^alex','alexadfadw')
['alex']
>>>
>>> re.findall('^alex','qalexadfadw')
[]
>>>

$是控制结尾的
>>> re.findall('alex$','qalexadfadw')
[]
>>> re.findall('alex$','qalexadfadwalex')
['alex']
>>>

*表示前面的字符出现0次或者多次
>>> re.findall('alex*','wwwalex')
['alex']
>>> re.findall('alex*','wwwale')
['ale']
>>>
>>> re.findall('alex*','wwwalexxxxxxx')
['alexxxxxxx']

+表示前面的字符出现1次或者多次
>>> re.findall('alex+','wwwalexxxxxxx')
['alexxxxxxx']
>>> re.findall('alex+','wwwale')
[]
>>>
?(英文状态下的问号)表示前面的字符出现0次或者1次
>>> re.findall('alex?','wwwale')
['ale']
>>> re.findall('alex?','wwwalex')
['alex']
>>> re.findall('alex?','wwwalexxx')
['alex']
>>>


#{3,5} x 匹配3到5次
>>> re.findall('alex{3}','wwwalexxxx')
['alexxx']
>>> re.findall('alex{3,5}','wwwalexxxx')
['alexxxx']
>>> re.findall('alex{3,5}','wwwalexxxxxxx')
['alexxxxx']
>>>

#[bc] b或者c
>>> re.findall('a[bc]d','wwwabd')
['abd']
>>> re.findall('a[bc]d','wwwacd')
['acd']
>>> re.findall('a[bc]d','wwwabcd')
[]
>>>
#查找关键字符 如.^$
>>> re.findall('a[.]d','wwwaqd')
[]
>>> re.findall('a[.]d','wwwa.d')
['a.d']
>>> re.findall('a[.^$]d','wwwa.d')
['a.d']
>>> re.findall('a[.^$]d','wwwa.ddfa^d')
['a.d', 'a^d']
>>> re.findall('a[.^$]d','wa$dwwa.ddfa^d')
['a$d', 'a.d', 'a^d']

#- 表示区间  [a-z] 表示a到z
>> re.findall('a[a-z]d','wwacd')
['acd']
>>> re.findall('a[a-z]d','wwacd12adfd')
['acd']
>>> re.findall('a[a-z]d','wwacd12afd')
['acd', 'afd']
>>> re.findall('[a-z]','wwacd12afd')
['w', 'w', 'a', 'c', 'd', 'a', 'f', 'd']
>>> re.findall('[1-9]','wwacd12afd')

#[^1-9] 里的^表示非的意思
>>> re.findall('[^1-9]','w3ww8a.d')
['w', 'w', 'w', 'a', '.', 'd']
>>>

>>> re.findall('[^1-9]','w3ww8a.d')
['w', 'w', 'w', 'a', '.', 'd']
>>> re.findall('[^1-9]','w3ww08a.d')
['w', 'w', 'w', '0', 'a', '.', 'd']




#\d表示匹配一个数字  两个\d表示匹配两个数字
>>> re.findall('\d','w3ww08a.d')
['3', '0', '8']
>>> re.findall('\d\d','w3ww08a.d')
['08']
>>>
#w 大小写字母 和0-9的数字
>>> re.findall('\w','w3ww08a.d')
['w', '3', 'w', 'w', '0', '8', 'a', 'd']
>>> re.findall('\w','w3wIw08a.d')
['w', '3', 'w', 'I', 'w', '0', '8', 'a', 'd']
>>> re.findall('\w','w3wIw*&08a.d')
['w', '3', 'w', 'I', 'w', '0', '8', 'a', 'd']
>>>
#\s 提取 空白,也就是 空格
>>> re.findall('\s','w3 ww08a.d')
[' ']
>>>

 
#search 找到一个就不会再往下匹配了  findall会查找有字符里并匹配,直到全部找完
>>> re.search('(ab)*','aba').group()
'ab'
>>> re.search('(ab)*','aba abcadfd').group()
'ab'
>>> re.search('alex','abalex').group()
'alex'
>>> re.search('alex','abalexadfadfalex').group()
'alex'
>>> re.findall('alex','abalexadfadfalex')
['alex', 'alex']
>>>

#match只匹配开始的内容
>>> re.match('alex','abalexadfadfalex')
>>> re.match('alex','alexadfadfalex')
<_sre.SRE_Match object; span=(0, 4), match='alex'>
>>> re.match('alex','alexadfadfalex').group()
'alex'
>>> re.search('alex','abalexadfadfalex').group()
'alex'
>>> re.findall('alex','abalexadfadfalex')
['alex', 'alex']



>>> re.findall(r'a(\d+)','a23b')
['23']
>>> re.search(r'a(\d+)','a23b')
<_sre.SRE_Match object; span=(0, 3), match='a23'>
>>> re.search(r'a(\d+)','a23b').group()
'a23'
>>> re.search(r'a(\d+)','a2234235653b').group()  # \d表示数字,+ 表示一个或者多个  
'a2234235653'
>>>
>>>#非贪婪模式 \d表示数字,+ 表示一个或者多个  ? 表示提取最小数 也就是提取一个 所以结果是a2
>>> re.search(r'a(\d+?)','a2234235653b')
<_sre.SRE_Match object; span=(0, 2), match='a2'>
>>> re.search(r'a(\d+?)','a2234235653b').group()
'a2'

#非贪婪模式 \d表示数字,* 表示0个或者多个、  ? 表示提取最小数 也就是提取0个  所以结果是a
>>> re.search(r'a(\d*?)','a2234235653b').group()
'a' 



>>> re.findall(r'a(\d+?)b','a22334we6573b')
[]
>>> re.findall(r'a(\d+?)b','a223346573b')  #findall提取组里面的内容
['223346573']
>>> re.findall(r'a(\d+?)','a223346573b')
['2']
>>> re.search(r'a(\d+?)','a223346573b')
<_sre.SRE_Match object; span=(0, 2), match='a2'>
>>> re.search(r'a(\d+?)','a223346573b').group()
'a2'
>>> re.search(r'a(\d+?)b','a223346573b').group()
'a223346573b'
>>>


# \2表示第二组的内容
>>> re.search(r"(alex)(eric)com\2","alexericcomeric").group()  
'alexericcomeric'



#\b可以用来找单词
>>> re.findall(r'\babc\b','abc adfadsfasdfasdfadfsa')
['abc']


#主要用到三个函数 search  findal match 

>> re.search('com','COM',re.I).group()
'COM'
>>> re.search('com','COM').group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>

#.S 标志位很少用到
>>> re.findall('.','abc\nde')
['a', 'b', 'c', 'd', 'e']
>>> re.findall('.','abc\nde',re.S)
['a', 'b', 'c', '\n', 'd', 'e']
>>>


>>> a = '123abc4566'
>>> re.search('([0-9]*)([a-z]*)([0-9]*)',a).group(0)
'123abc4566'
>>> re.search('([0-9]*)([a-z]*)([0-9]*)',a).group()  #默认是0
'123abc4566'
>>> re.search('([0-9]*)([a-z]*)([0-9]*)',a).group(1)
'123'
>>> re.search('([0-9]*)([a-z]*)([0-9]*)',a).group(2)
'abc'
>>> re.search('([0-9]*)([a-z]*)([0-9]*)',a).group(3)
'4566'
>>>


#sub 和subn的区别,subn最后会返回被替换的次数 
>>>
>>> re.sub('g.t','have','I get A ,  I got B ,I gut C ')
'I have A ,  I have B ,I have C '
>>> re.sub('g.t','have','I get A ,  I got B ,I gut C ',1)
'I have A ,  I got B ,I gut C '
>>> re.sub('g.t','have','I get A ,  I got B ,I gut C ',2)
'I have A ,  I have B ,I gut C '
>>>

>>> re.subn('g.t','have','I get A ,  I got B ,I gut C ')
('I have A ,  I have B ,I have C ', 3)  #一共被替换了3次


compile的使用  split的使用


>>>
>>> p = re.compile(r'\d+')
>>> p.split('one1two2threee3four4')
['one', 'two', 'threee', 'four', '']
>>> p.split('4one1two2threee3four4')
['', 'one', 'two', 'threee', 'four', '']
>>>


>>> re.search('\([^()]*\)','1-2(9-3+3+4)+3').group()
'(9-3+3+4)'


\d+\.?\d*  \.表示转移字符 



#/usr/bin/env python
# -*- coding: UTF-8 -*-
import re
p = re.compile(r'\d+')
w =p.finditer('12 afdafd 4 ljadlfja...adfd10')
print(w)
for x in w:
    print(x.group(),x.span())

    
    
    
正则表达式测试IP 地址    


>>> f = open('d:\abc.txt')   因为\a在pyhton里是具有特殊功能的字符,\a是响铃符
Traceback (most recent call la st):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument: 'd:\x07bc.txt'
>>>

\n\b\t 在python里本身就具备功能
\\ 在python里 变成了一个反斜杠
\\\\  在python里 变成了两个反斜杠



>>> re.findall('\\\\','abc\com')
['\\']
>>> re.findall(r'\\','abc\com')  r表示原生字符串
['\\']
>>>



>>> re.findall(r'\d','w4ww6')
['4', '6']
>>> re.findall('\d','w4ww6')
['4', '6']
>>> re.findall('\d*','w4ww6')
['', '4', '', '', '6', '']
>>> re.findall(r'\d*','w4ww6')
['', '4', '', '', '6', '']
>>>


>>> re.match('\bblow','blow')
>>> re.match('\\bblow','blow')
<_sre.SRE_Match object; span=(0, 4), match='blow'>
>>> re.match('\\bblow','blow').group()
'blow'
>>> re.match(r'\bblow','blow').group()
'blow'


>> import re
>>> re.findall('abc\b','asdas abc ')
[]
>>> re.findall(r'abc\b','asdas abc ')
['abc']
>>> re.findall(r'abc\b','asdas abc*')
['abc']
>>> re.findall(r'I\b','I MISS YOU')
['I']
>>> re.findall(r'I\b','IMISS YOU')
[]

>>> re.findall('www.(baidu|laonahai).com','asad www.baidu.com')
['baidu']
>>> re.findall('www.(baidu|laonahai).com','asad www.laonahai.com')
['laonahai']
>>>

>>> re.findall(r'\bI','IMISS YOU')
['I']
>>> re.findall(r'\bI','IMISS YOU')
['I']
>>> re.findall(r'\bI','IMISS IOU')
['I', 'I']
>>> re.findall('abc\\b','asdas abc ')
['abc']
>>>

#?: 去掉优先获取组的权限
>>> re.findall('www.(?:baidu|laonahai).com','asad www.laonahai.com')
['www.laonahai.com']
>>>
正则表达式案列

 

正则表达式  武沛奇

python中re模块提供了正则表达式相关操作

 

字符:

 

  . 匹配除换行符以外的任意字符
  \w 匹配字母或数字或下划线或汉字
  \s 匹配任意的空白符
  \d 匹配数字
  \b 匹配单词的开始或结束
  ^ 匹配字符串的开始
  $ 匹配字符串的结束

 

次数:

 

  * 重复零次或更多次
  + 重复一次或更多次
  ? 重复零次或一次
  {n} 重复n次
  {n,} 重复n次或更多次
  {n,m} 重复n到m次

 match

# match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
  
  
 match(pattern, string, flags=0)
 # pattern: 正则模型
 # string : 要匹配的字符串
 # falgs  : 匹配模式
     X  VERBOSE     Ignore whitespace and comments for nicer looking RE's.
     I  IGNORECASE  Perform case-insensitive matching.
     M  MULTILINE   "^" matches the beginning of lines (after a newline)
                    as well as the string.
                    "$" matches the end of lines (before a newline) as well
                    as the end of the string.
     S  DOTALL      "." matches any character at all, including the newline.
  
     A  ASCII       For string patterns, make \w, \W, \b, \B, \d, \D
                    match the corresponding ASCII character categories
                    (rather than the whole Unicode categories, which is the
                    default).
                    For bytes patterns, this flag is the only available
                    behaviour and needn't be specified.
       
     L  LOCALE      Make \w, \W, \b, \B, dependent on the current locale.
     U  UNICODE     For compatibility only. Ignored for string patterns (it
                    is the default), and forbidden for bytes patterns.
# 无分组
        r = re.match("h\w+", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组结果

        # 有分组

        # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)

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

Demo
demo

search 

# search,浏览整个字符串去匹配第一个,未匹配成功返回None
# search(pattern, string, flags=0)
# 无分组

        r = re.search("a\w+", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组结果

        # 有分组

        r = re.search("a(\w+).*(?P<name>\d)$", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

demo
demo

findall

# findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
# 空的匹配也会包含在结果中
#findall(pattern, string, flags=0)
# 无分组
        r = re.findall("a\w+",origin)
        print(r)

        # 有分组
        origin = "hello alex bcd abcd lge acd 19"
        r = re.findall("a((\w*)c)(d)", origin)
        print(r)

Demo
demo

sub

# sub,替换匹配成功的指定位置字符串
  
sub(pattern, repl, string, count=0, flags=0)
# pattern: 正则模型
# repl   : 要替换的字符串或可执行对象
# string : 要匹配的字符串
# count  : 指定匹配个数
# flags  : 匹配模式
 # 与分组无关

        origin = "hello alex bcd alex lge alex acd 19"
        r = re.sub("a\w+", "999", origin, 2)
        print(r)

  split

# split,根据正则匹配分割字符串
  
split(pattern, string, maxsplit=0, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# maxsplit:指定分割个数
# flags  : 匹配模式
# 无分组
        origin = "hello alex bcd alex lge alex acd 19"
        r = re.split("alex", origin, 1)
        print(r)

        # 有分组
        
        origin = "hello alex bcd alex lge alex acd 19"
        r1 = re.split("(alex)", origin, 1)
        print(r1)
        r2 = re.split("(al(ex))", origin, 1)
        print(r2)

Demo
demo
 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.match() #从头开始匹配 最常用  

无分组

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
# re.match()  #从头开始匹配   最常用  无分组
import re
"""
匹配模式:以下四种模式最多
re.S(DOTALL)   使.匹配包括换行在内的所有字符
re.I(IGNORECASE)  使匹配对大小写不敏感
re.M(MULTILINE)   多行匹配,影响 ^ 和$
re.X(VERBOSE)  该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
"""
#因没有分组所以  groups,groupdict 结果为空
origin = "hello alex bcd abcd  lge acd 19"
r = re.match('h\w+',origin)
print(r.group())  # 获取匹配到的所有结果             结果为:hello
print(r.groups())  # 获取模型中匹配到的分组结果      结果为:()
print(r.groupdict())  # 获取模型中匹配到的分组结果   结果为:{}

  有分组 案列一

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
# re.match()  #从头开始匹配   最常用  无分组
import re
"""
匹配模式:以下四种模式最多
re.S(DOTALL)   使.匹配包括换行在内的所有字符
re.I(IGNORECASE)  使匹配对大小写不敏感
re.M(MULTILINE)   多行匹配,影响 ^ 和$
re.X(VERBOSE)  该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
"""
#有分组
origin = "hello alex bcd abcd lge acd 19"
# r = re.match("h(\w+)", origin)   #  执行结果 group  hello、groups  ('ello',)、 groupdict {}
# r = re.match("(h)\w+", origin)    #  执行结果 group  hello、groups  ('h',)、 groupdict {}
# r = re.match("(h)(\w+)", origin)  # 最常见      执行结果 group  hello、groups  ('h', 'ello')、 groupdict {}
r = re.match("(?P<n1>h)(?P<n2>\w+)", origin)  # 输出结果为字典 最常见 执行结果 group  hello、groups  ('h', 'ello')、 groupdict {'n1': 'h', 'n2': 'ello'}
print(r.group())  # 获取匹配到的所有结果
print(r.groups())  # 获取模型中匹配到的分组结果
print(r.groupdict())  # 获取模型中匹配到的分组结果

ps: ?P<n1> 表示指定键值对里的键值    分组就是提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)

 有分组 案列二

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
# re.match()  #从头开始匹配   最常用  无分组
import re
"""
匹配模式:以下四种模式最多
re.S(DOTALL)   使.匹配包括换行在内的所有字符
re.I(IGNORECASE)  使匹配对大小写不敏感
re.M(MULTILINE)   多行匹配,影响 ^ 和$
re.X(VERBOSE)  该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
"""
#默认匹配模式是贪婪匹配 所以 \d只匹配到了9 
origin = "hello alex bcd abcd lge acd 19"
r = re.match("h(\w+).*(?P<name>\d)$", origin)
print(r.group())  # 获取匹配到的所有结果  执行结果:hello alex bcd abcd lge acd 19
print(r.groups())  # 获取模型中匹配到的分组结果  执行结果:  ('ello', '9')
print(r.groupdict())  # 获取模型中匹配到的分组中所有执行了key的组    执行结果:  {'name': '9'}
 re.search() 浏览全部字符串,匹配第一个符合规则的字符串(只找第一个)
#/usr/bin/env python
# -*- coding: UTF-8 -*-)
# re.search() 浏览全部字符串,匹配第一个符合规则的字符串(只找第一个)
#无分组    
import re
# origin = "hello alex中奖 bcd abcd lge acd 19"
# r = re.search("a\w+", origin)
# print(r.group())     # 获取匹配到的所有结果   执行结果:alex中奖
# print(r.groups())    # 获取模型中匹配到的分组结果  执行结果:()
# print(r.groupdict()) # 获取模型中匹配到的分组结果 执行结果: {}

 # 有分组
origin = "hello alex中奖 bcd abcd lge acd 19"
r = re.search("a(\w+).*(?P<name>\d)$", origin)
print(r.group())     # 获取匹配到的所有结果         执行结果:alex中奖 bcd abcd lge acd 19
print(r.groups())    # 获取模型中匹配到的分组结果   执行结果:('lex中奖', '9')
print(r.groupdict()) # 获取模型中匹配到的分组结果    执行结果:{'name': '9'}
 re.findall()   最常用 将匹配到的所有内容放入到一个列表里 案列一
#/usr/bin/env python
# -*- coding: UTF-8 -*-)
# re.findall()   最常用 将匹配到的所有内容放入到一个列表里
# 无分组
import re
n = re.findall('\d+\w\d+', 'a2b3c4d5')
print(n)# 执行结果为 ['2b3','4d5']
# 匹配流程   a匹配失败,从2开始匹配,2b3匹配成功,拿走。从c开始匹配,c匹配失败。从4开始,4d5匹配成功
# 正则表达式匹配顺序是一次往后找,(如果匹配成功的直接跳过)

n = re.findall('', 'a2b3c4d5')
print(n)  # 如果没有匹配的,还会把空值放到结果里  八个字符会出现九个空白字符

origin = "hello alex中奖600万 bcd abcd lge acd 19"
r = re.findall("a\w+", origin)
print(r)  #执行结果  ['alex中奖600万', 'abcd', 'acd']

# 有分组
origin = "hello alex bcd abcd lge acd 19"
r = re.findall("a((\w*)c)(d)", origin)
r2 = re.findall('a(\w*)(d)',origin)
print(r)
print(r2)

 案列二、

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
import re
#finall
origin = "hello alex bcd abcd lge acd 19"
n1 = re.findall('a\w+',origin)
n2 =  re.findall("(a)(\w+)", origin)
n3 =  re.findall("(a)(\w+)(x)", origin)
print(n1)   # 执行结果 ['alex', 'abcd', 'acd']
print(n2)   #执行结果 [('a', 'lex'), ('a', 'bcd'), ('a', 'cd')]
print(n3)   #执行结果 [('a', 'le', 'x')]

 findall 分组里套分组      将匹配到的所有内容放入到一个列表里

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
import re
# 分组里套分组
origin = "hello alex中奖600万 bcd abcd lge acd 19"
origin = "hello alex bcd abcd lge acd 19"
r1 = re.findall("(a)(\w+(e))(x)", origin)
r2 = re.findall("(a)((\w+)(e))(x)", origin)
r3 = re.findall("(a)((\w+)(e))(?P<n1>x)", origin)  # ?P<n1>不起最用 ,在findall里无效
print(r1)
print(r2)
print(r3)
# 一个一个去找  a   \w + e 找到le再往里找是e所以结果为a, le, e, x从左到右,从外边到内边分组就是在已经匹配到的数据里再进行匹配匹配规则从左到右,从外边到内边finditer是迭代的方式

origin = "hello alex bcd abcd lge acd 19"
r3 = re.finditer("(a)((\w+)(e))(?P<n1>x)", origin)  # 以后会经常使用
print(r3)
for i in r3:
    print(i.group(),i.groups(),i.groupdict())

 综合案列:

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
"""
group   匹配所有内容,有括号也是匹配原来的 内容
groups    groups 在有括号的时候,在再次匹配括号的内容, 并显示出来
groupdict
findall 是挨个顺序去找   findall 其实就是一个一个search
"""
import re
origin = '6asd2asdp3asd3338asd98kif'
n = re.findall(r'(\d+asd)',origin)
#默认是贪婪匹配 n1的匹配顺序是\d+asd 匹配到 6asd2asd 因是贪婪匹配而且加上了 括号 所以只取2asd ,p不否和成为 ''
#接着\d+asd  匹配到 3asd3338asd,因是贪婪匹配所以匹配到3338asd,其他不否和所以为'',之所以为空 是因为 * 可以匹配空元素
n1 = re.findall(r'(\d+asd)*',origin)  #默认是贪婪匹配
n2 =  re.findall(r'(\d+asd)+',origin) #原理同上 + 不能匹配空值,+ 是1到无穷元素,所以不匹配空值
print(n)
print(n1)
print(n2)

num = '5asd2asdp3asd98kif'
r = re.findall('\dasd',num)
r2 = re.findall('(\dasd)*',num)
r3 = re.findall('(\dasd)+',num)
print(r)
print(r2)  #打印最后 会多个 '' ,要尽量避免空值 ,因为空有一个特性
print(r3)


num5 = '1asd2asdp3asd3338asd98kif'
n2 = re.finditer('(\dasd)*',num5)
# n2 = re.finditer('(\dasd)',num5)
print(n2)
for i in n2:
    print(i,i.group(),i.groups(),i.groupdict())




#findall 默认会加空值,如 匹配4个字符,用空来匹配会出现5个空字符
n5 = re.findall('','abcd')
print(n5)
#注意 {}、*、+ 的效果
a = 'alex'
n = re.findall('(\w+)',a)
n1 = re.findall('(\w)(\w)(\w)(\w)',a)  #数据结果 为 a  l  e x
n2 = re.findall('(\w){4}',a)  #  输出结果为  x  {4}个表示4个{\w},但是只出现里一个(\w)组的意思,所以groups默认只会提取最后一个
n3 = re.findall('(\w)*',a) #*表示0次或者多次 默认是贪婪模式
n4 = re.findall('(\w)+',a) #+表示1次或者多次 默认是贪婪模式
print(n)
print(n1)
print(n2)
print(n3)
print(n4)

split 分割

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
import  re
origin = "hello alex bcd abcd lge acd 19"
origin.split('a')
#无分组 分割的时候不包含自己
n = re.split('a\w+',origin)
n2 = re.split('a\w+',origin,1)  #看源码  看参数  1 表示分割次数
print(n)
print(n2)


#有分组 分割的时候会包含自己
origin = "hello alex bcd abcd lge acd 19"
n3 = re.split('(a\w+)',origin,1)  #看源码   1 表示分割次数
print(n3)

n4 = re.split('a(\w+)',origin,1) #1 表示分割次数  a(\w+) 匹配到alex ,但是有括号,再匹配括号里的匹配到 lex
print(n4)

n5 = re.split('a(\w+)x',origin,1) # a(\w+)x 匹配到alex ,但是有括号,再匹配括号里的匹配到 le
print(n5)

  SUB 正则替换

#/usr/bin/env python
# -*- coding: UTF-8 -*-)
#sub 替换,默认是替换所有,可以指定数字
import re
origih = 'iyik3adfkkad897adfk23ka'
print(origih)
new_str = re.sub('\d+', 'KKK', origih, 1)
new_str2 = re.sub('\d+', 'KKK', origih)  # 默认是所有
print(new_str)
print(new_str2)
print('**********subn共可以替换多少次****************')
origih6 = 'ad2dkj89was90'
new_str6,count= re.subn('\d+', 'KKK', origih6)
print(new_str6, count)

  

  

 

 

 

  

  

  

 

  

posted @ 2018-05-28 09:54  奋斗的小孩_小小鸟  阅读(261)  评论(0)    收藏  举报