• (3)re模块(正则表达式模块)


    什么是正则表达式

    正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

    生活中处处都是正则:

    比如我们描述:4条腿你可能会想到的是四条腿的动物或者桌子,椅子等

    继续描述:4条腿,活的就只剩下四条腿的动物这一类了

    正则表达式格式

    re.findall(pattern,string,flags)

    pattern:正则表达式

    string:被匹配的字符串

    flags

    匹配原理

    匹配字符中的alex

    print(re.findall('alex','my name is alex alex is DSB'))

    PS:从字符串中找出符合规则的,正则表达式‘alex’就是规则,程序就会先从字符串第一个字符开始匹配,没有匹配上则往后走一个,如果遇到第一个字符匹配成功,则开始从成功被匹配的字符开始往后匹配第二个字符,如不成功则直接往后走一个字符,从头开始匹配,直到表达式全部匹配成功,如全部没有匹配成功则

    正则符号对应的功能

    正则匹配(findall方法)

    import re  #调用re模块

    findall方法返回的是一个列表,所有符合表达式的值都存在这个列表中

    转义符号 (取消特殊字符的意义)
    print(re.findall('a.c','a.c a1c aac aAc'))

    PS:加上转义符号 就会变成普通符号

    字符串末尾匹配 $

    print(re.findall('DSB$','alex my name is alex alex is DSB '))  #  $ 表示匹配字符串的末尾

    匹配任意字符  .

    print(re.findall('a.c','abc a c a1c aaaaaaac a c a c',re.DOTALL))  # . 代表匹配一个字符,这一个字符可以是除了 以外的任意字符

    匹配指定范围字符 []

    print(re.findall('a[0-9]c','a1c a2c aac aaaac aAc'))  #  [ ] 代表匹配一个字符,这一字符必须是指定范围内的,[0-9] [a-zA-Z],只要ac中间是匹配项都会获取
    print(re.findall('a[A-Z]c','a1c a2c aac aaaac aAc'))  #ac中间是大写字母都会获取
    print(re.findall('a[A-Za-z]c','a1c a2c aac aaaac aAc')) #ac中间是字母,包含大小写均可
    print(re.findall('a[A-Za-z][A-Za-z]c','a1c a2c aac aaaac aAc')) # ac中间两个字符必须是大小写字母
    print(re.findall('a[+*/-]c','a-c a+c a*c a/c aaac a1c asadfac'))  
    print(re.findall('a[^+*/-]c','a-c a+c a*c a/c aaac a1c asadfac'))

    PS:正则表达式时候, - 这个符号如果放在中间则表示是范围的意思,所以需要匹配横杠时候放左右两面即可

    重复匹配  ? 和 * 和 + 和 {n,m}

    print(re.findall('ab?','a ab abb abbb abbbbbbb a1b a+b'))  # ? 左边b这一个字符出现0次或1次

    print(re.findall('ab*','a ab abb abbb abbbbbbb a1b a+b'))  # * 左边b这一个字符出现0次或无穷次

    print(re.findall('ab+','a ab abb abbb abbbbbbb a1b a+b'))  # + a后面至少有一个b,如果没有则匹配不成功,如果有则表示有多少拿多少

    print(re.findall('ab{0,3}','a ab abb abbbb ')) # {n,m} n就是设定表达式右边的数值b出现次数,m就是b出现次数上限,如果m为空就是无穷次

    贪婪匹配  .* 

    print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']  # .*  默认为贪婪匹配

    PS:从a开始就往右面一直找,直到找到最远的b为止

    PS:.*合并到一起是一个组合和单纯的.是不一样的意思

     

    非贪婪匹配  .*?(推荐使用)

    print(re.findall('a.*?b','a1b22222222b'))  #  *?是组合在一起使用的,这里的?只是单纯的非贪婪模式的表示,和重复匹配里的?毫无关系

    PS:从a开始找最近的b

    或者匹配 |
    print(re.findall('company|companies','Too many companies have gone bankrupt, and the next one is my company'))  #查找公司的单词,匹配多个条件

    分组法

    print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))  #分组的开头加?:这是一个固定的用法,表示所取得结果包括组内组外,如果不加?:则表示所取得结果就是组内匹配成功的

    print(re.findall('href="(.*?)"','<a href="https://www.baidu.com/1.mp4"><p>"哈哈哈"</p><a href="https://www.baidu #查找网页链接

    PS:|是或者的意思

    PS:分组法括号前面的是辅助匹配条件,这个条件达到后再去匹配括号里面的,括号里相同的条件值会被取出

    正则表达实例

    取出表达式中的所有数字

    print(re.findall('D?(-?d+.?d*)',"1-12*(60+(-40.35/5)-(-4*3))"))

    匹配逻辑

    先设定 D?  要判定是否是负数,- 号的前面必须是非数字(也就是括号),所以优先设定一个非数字匹配而且只出现1次  #这是一个辅助匹配

    -?  然后再设定减号出现1次或0次来匹配负数(用转义符 将 - 变成普通符号) 

    先用 d 匹配任意数字,然后再设定一个条件 +至少出现一次

    用 .匹配普通字符 .  (用转义符将 . 变成普通的字符 .)去匹配数字.后面的字符 ,加上?设定出现0次或1次

    然后用 d* 匹配无穷个普通数字  (数字后面的小数点不一定是必须出现的,整数肯定是没有的,只有浮点数小数点后面跟数字)小数点后面可能出现无穷的数字

    最后将'D? 后面的表达式全部用()括起来,使用分组法去匹配

    取出ac 这个字符串

    print(re.findall('a\c','abc a1c a c ac'))

    PS:在正则表达式中是转义的意思,所以不能单用一个去匹配,必须用转义符将转义成普通字符串,如果只用一个 去转义,则程序会默认把c识别成一组进行转义,由于Python解释器在读取的时候有一个解析过程,即a\c解析后就是a\c,\就表示普通的 这个符号,所以要加两个\

    re模块的其他方法

    search方法

    和findall一样的功能都是查找字符串,findall返回的是一个列表,但是search会返回一个对象,并且告诉你这个对象的索引范围位置,但是只找最前面的一个,所以这个方法通常用来判断字符串里面有没有符合我设定规则的,如果有则不会再找下去,没找到就返回None

    print(re.search('alex','myalex alex is DSB'))

    serach下的.group功能用来返回查找的对象,即返回serach匹配成功的对象,如果对象不存在则报错

    print(re.search('alex','myalex alex is DSB').group()) 

    search下的match功能,match表示从头开始匹配,等同于 ^ 这个符号

    print(re.search('^alex','alex alex is DSB'))  #加一个 ^ 这个符号则表示从头开始匹配

    print(re.match('alex','alex alex is DSB').group())   #match和^一样都是从头开始匹配

    re.split方法

    正则表达式中的切分法

    info='a:=-b*(c'  #将变量中的字母切分出来

    print(re.split('[:=*(-]',info))  #直接切分后返回的列表中会有空字符

    res=[item for item in re.split('[:=*(-]',info) if len(item) != 0]  #用列表表达式可以剔除空字符
    print(res)

    PS:如果直接切分会在字典中出现空字符,配合列表解析加判定过滤即可,为什么会出现空字符,因为在分割时候如果遇到表达式中的符号,则左右都是空,则会将空字符放入列表

    sub方法(这个方法下flags有很多种可供选择

    re.sub(pattern, repl, string, count=0, flags=0)

    re.sub 用于替换字符串的匹配项。如果没有匹配到规则,则原字符串不变。

    pattern:正则表达式

    repl:替换后的字符串 

    string:需要处理的字符串 

    count:替换多少次,默认是0,从头到尾做替换

    flags:匹配模式

    替换字符串中的字符

    msg='alex my name is alex alex alex is hahahah'

    print(re.sub('^alex','ALEX',msg)) #加^ 则表示值替换开头的

    print(re.subn('alex','ALEX',msg)) #返回一个替换后的内容元祖,并且告诉你替换了几处

    print(re.sub('alex','SB',msg,flags=re.I))  # 指定模式 re.I 则是表示省略大小写

    PS:正则表达式的替换操作,加^这个符号则可以控制替换开头一个

    PS:sbu比replace强大的地方就是可以指定替换位置,而replace不能控制

     

    匹配出所有每一行末尾指定字符

    msg="""
    a1231231231231egon
    123123sadfsadf2143egon
    sdafljsalfdjerwqregon
    """
    print(re.findall('egon$',msg,flags=re.M))  #re.M是多行的意思

    了解利用sub将字符串替换位置

    msg="my name is"

    msg="单词1 单词2 单词3"

    msg="单词3 单词2 单词1"

    print(re.sub('([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)',r'52341',msg))

    PS:将每一个单词用()进行分组,每一个分组对应一个位置,最后将分组的序号进行排位就行

    PS: ^就是取反的意思,即不是字母

    compile方法

    可以自定义一个正则表达式如果一个正则表达式常用,则可以用compile方法定义成一个变量
    pattern=re.compile('href="(.*?)"')  #这里自定义正则表达式
    print(pattern.findall('<a href="https://www.baidu.com/1.mp4"><p>"哈哈哈"</p><a href="https://www.baidu.com/2.mp4">'))
    print(pattern.findall('<a href="https://www.baidu.com/1.mp4"><p>"哈哈哈"</p><a href="https://www.baidu.com/2.mp4">'))
    print(pattern.findall('<a href="https://www.baidu.com/1.mp4"><p>"哈哈哈"</p><a href="https://www.baidu.com/2.mp4">'))
    PS:在调用时候直接将字符串传入则可以做匹配

  • 相关阅读:
    libevent源码分析--(转)
    libevent源码分析(转)
    服务器模型---总结
    暴力英语学习法 + 严格的目标管理 = 成功快速靠谱的学好英语(转)
    log4net写入mysql完整例子
    form操作
    ASP.NET Razor
    java爬虫:在请求body中增加json数据采集
    asp.net mvc3登录验证
    远程复制无法读取源文件或磁盘
  • 原文地址:https://www.cnblogs.com/shizhengquan/p/10052817.html
Copyright © 2020-2023  润新知