• Python之路【第二十一篇】:正则表达式


    正则表达式用于进行字符匹配,在正则表达式中有普通字符和元字符两种字符

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

    字符:

      . 匹配除换行符以外的任意字符
      w 匹配字母或数字或下划线或汉字

      W 匹配非字母或数字或下划线或汉字
      s 匹配任意的空白符,相当于[  fv]

      S 匹配任何非空白字符,相当于[^ fv]
      d 匹配数字

      D 匹配非数字,相当于[^0-9]
       匹配单词的开始或结束
      ^ 匹配字符串的开始
      $ 匹配字符串的结束

    [] 字符集,在字符集中,一般的元字符就是去意义了,但也有没有失去意义的;例如[bc],b或c;[a-z] ;[^1-9],非的作用,除了1-9;

    () 表示分组

    | 表示或的意思,如([*/]|**)就表示乘除或者幂运算

    次数:

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

    下划线

    后面跟元字符的话去除元字符的特殊功能,
    跟普通字符的话就会实现特殊功能
    引用序号对应的字组所匹配的字符串,如:"(alex)(eric)com2",一个括号一个组,说明com后面还有匹配一个eric

    贪婪匹配与非贪婪匹配

    比如说*重复前一个字符零次或更多次,贪婪匹配的话就是按照最大的来匹配

    在*后面加上?就变成非贪婪匹配了

    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, 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, 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("hw+", 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的组

    search

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

    代码示例

    # 无分组
    r = re.search("aw+", 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的组

    findall

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

    代码示例

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

    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("aw+", "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)

    附加说明

    re.match(规则,字符串,标志位),标志位是说明匹配的方式,re.I使匹配对大小写 不敏感,re.L做本地化识别匹配,re.M多行匹配,re.S使.匹配包含换行符在内的所有字符

    re.search(规则,字符串,标志位),标志位是说明匹配的方式,re.I使匹配对大小写不敏感,re.L做本地化识别匹配,re.M多行匹配,re.S使.匹配包含换行符在内的所有字符

    match和search匹配成功之后会返回一个对象,需要调用相应的方法来进行输出:group()返回匹配的字符串,start()返回匹配开始的位置,end()返回匹配结束的位置,span()返回一个元组包含(开始,结束)的位置
    group()默认参数为0,group(n),返回组号为n所匹配的字符串,group(n,m)返回组号为n,m所匹配的字符串

    sub(规则,新的字符串,旧的字符串,max=0)用于替换,max用于规定替换几个,如果不加max最后面这个参数,返回时会返回替换好的字符串和一个数字,表示替换了几次

    compile,把象,可以把那些经常需要匹配的表达式编译成正则表达式对象,这样可以提高一定的效率

    在组的前后均有限制条件的话,用于非贪婪匹配的?就不起作用了?有一个正则表达式,如:a(d+)b,字符串为a23b,使用findall结果是23,使用search结果是a23b,并且此时使用?,也不会变为非贪婪模式

    在python中 a 等都有一些特殊意思,举个例子
    f=open('d:abc.txt','r')会报错,因为a有特殊含义,所以需要加 ,f=open(r'd:abc.txt','r')
    在字符串前面加r就表示原生字符串
    在很多情况下,使用findall函数会优先获取组里面的内容,这时候在前面加?:就可以把这种权限取消,例如:'www.(?:baidu).com',这样就会匹配出www.baidu.com而不是只匹配出baidu

    常用正则表达式

    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_-]+)+

     随堂笔记

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import re
    
    #使用模块要看模块的源文件
    #默认情况下是贪婪的
    #最常用的re函数,match与findall最常用
    # re.match()        匹配开头
    # re.search()       浏览全部字符串,匹配第一个符合规则的字符串
    # re.findall()      将匹配到的所有内容放入一个列表中
    # #re.finditer()    与findall的区别类似于range与xrange分区别,只有迭代才能输出
    # re.split()
    # re.sub()
    
    #match,search,findall这些方法概括起来有两种匹配方式:简单匹配和分组匹配
    #match,search会返回一个对象,对象里有多种方法,这些对象里最最基本的有group(),groups(),groupdict()这三个方法
    #match,search,findall里面都有三个参数,正则表达式,源字符串,标志位
    #为何要有分组
    #分组就是取已经匹配到的内容里取取值,有几个括号就取几次,不管嵌套有多深
    #简单匹配
    
    orign = 'hello alex bcd alev lge alec acd 19'
    r = re.match('(h)(w+)',orign)
    print(r.group()) #获取匹配到的所有结果
    print(r.groups())#获取模型中匹配到的分组结果
    
    r = re.match('(?P<n1>h)(?P<n2>w+)',orign)
    print(r.groupdict())#获取模型中匹配到的分组中所有执行了key的组
    #?P<键>固定写法
    
    #search与match一样,只不过一个匹配开头,一个匹配第一个
    orign = 'hello alex bcd alev lge alec acd 19'
    r = re.search('(a)(w+)',orign)
    print(r.group())
    print(r.groups())
    
    r = re.search('(?P<n1>a)(?P<n2>w+)',orign)
    print(r.groupdict())
    
    print(re.findall('d+wd+','a2b3c4d5'))
    #输出结果为[2b3,4d5]匹配的顺序是这样的,匹配到2b3后,再从c开始往后匹配,匹配到4d5
    #正则表达式匹配的顺序没有匹配到的时候是按个往后找,一旦匹配到,把匹配到的拿走,从匹配后的往后找
    print(re.findall('','a2b3c4d5'))
    #注意看这句的输出结果为['', '', '', '', '', '', '', '', '']
    
    
    #分割
    origin = 'hello alex bcd abcd lge acd 19'
    print(re.split('aw+',origin,1))
    #输出结果为:['hello ', ' bcd abcd lge acd 19']
    print(re.split('(aw+)',origin,1))
    #输出结果为:['hello ', 'alex', ' bcd abcd lge acd 19']
    print(re.split('a(w+)',origin,1))
    #输出结果为:['hello ', 'lex', ' bcd abcd lge acd 19']
    
    #1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
    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))'
    print(re.findall('([^()]+)',origin))
    #可以取得内层括号
    #输出结果为:['(-40.0/5)', '(9-2*5/3+7/3*99/4*2998+10*568/14)', '(-4*3)', '(16-3*2)']
    
    #利用re.split() 写计算器
    
    re.sub()
    #替换
    三样东西有助于缓解生命的疲劳:希望、睡眠和微笑。---康德
  • 相关阅读:
    javaWeb 使用jsp开发 if else 标签
    javaWeb 使用jsp开发 if 标签
    javaWeb 使用jsp标签进行防盗链
    javaWeb 在jsp中 使用自定义标签输出访问者IP
    javaWeb el表达式和jstl快速入门案例
    javaWeb 使用 jsp 和 javaBean 实现计算器功能
    javaWeb 使用cookie显示上次访问网站时间
    javaWeb 使用cookie显示商品浏览记录
    javaWeb request乱码处理
    ubunu下用命令设置壁纸
  • 原文地址:https://www.cnblogs.com/ronghe/p/8796102.html
Copyright © 2020-2023  润新知