经验拾忆(纯手工)=> Python正则全解详解

预编译

import re
re1 = re.compile(r'元字符 组成的正则规则')    # 元字符下面会说
re1.方法()                     # 方法下边也会说

元字符:

表示普通字符:
    .    # 除了\n外 均可以匹配的到                
    \d   # 只匹配 纯数字 0-9
    \D   # 和 \d相反, 除了数字全都匹配
    \s   # 只匹配空格
    \S   # 和 \s相反,除了空格,全都匹配         # 我喜欢用 [\s\S]*? 匹配全部
    \w   # 只匹配 纯数字 或 大小写字母 或 下划线
    \W   # 与 \w 刚好相反,     除了 纯数字、大小写字母、下划线 全都匹配
    []   # [abcde] 只要包含这个列表的字符,均可以匹配的到。但默认只取一个, 简写 [a-e]
             eg: re.compile(r'[e-h]').match('hello python ').group(0)
             >>> h
         此外:  [^abcde] 或 [^a-e] 表示 '排除',意思就是 除了abcde全匹配
    
匹配表示边界的:
    ^    # 匹配 起始 位置,受 re.M 影响     #注意:不要和 [^123] 除123以外搞混
         eg:
            import re
            r1 = re.compile(r'^\d+')
            print(r1.search('456hello123').group())
            >>> 456

    $    # 匹配 结尾 位置,受 re.M 影响
         eg:
            import re
            
            s = """
            123abc456
            678abc789
            """
            r1 = re.compile(r'\d+$',re.M)    # 注意这里加入了re.M
            print(r1.findall(s))
            >>> ['456', '789']    # 这是写了re.M,就意味着 每一行都给你单独按照规则处理
            >>> ['789']           # 若是没写re.M, 那么就按照总体,去最后一行的尾部
            注: 其实re.M的本质是 是根据\n,进行 断行,断行后对每一行按照规则单独处理
            
    \b: # 匹配 单词的 边界(除了 数字、中英字母、下划线 的 全部符号)
        eg:
            import re
            s = '你好啊----好个P'
            r1 = re.compile(r'\b好')
            print(r1.findall(s))
            >>> 好    
            # 解释:这个‘好’是,后面  的那个。由于后面的 ’好‘ 字 左边是符号,而非单词字符
                       
    \B: # 匹配 单词 非 边界(包括 数字、中英字母、下划线)
        eg:
            import re
            s = '你好啊----好个P'
            r1 = re.compile(r'\b好')
            print(r1.findall(s))
            >>> 好    
            # 解释:这个‘好’是,前面  的那个。由于前面的 ’好‘ 字 左边是中文字符。属于非边界
            # 因此就匹配上了
        
        再次总结: \b 与 \B:
            \b: 匹配边界字符。边界字符:(除了 数字、字母、汉字、下划线的全部符号)
            \B: 匹配非边界字符。非边界字符:(数字、字母、汉字、下划线)
    
匹配表示数量的:
    *    :    0次 或 屡次                    eg: 你*
    +    :    1次 或 屡次                    eg:  你+
    ?    :    0次 或 一次                    eg:  你?
    {m}  :     出现m次                        eg:  你{3}
    {m,} :    至少 出现m次                   eg:  你{3,}   # 涉及到贪婪模式,不深的不要用
    {m,n}:     m次 到 n次  之间任意一次就行    eg:  你{3,6}
    
表示分组:
    |    : 至关于或运算符, 两边写的是 正则表达式,  优先选择左边的
    ()   :  括起来里面的内容,就变成了分组。 能够用 .group(1)提取,若是有更多那就 group(2)..
    (?P<name>) : 在上面分组的基础上 起别名
    (?P=name)  :  根据分组的别名来使用分组
        eg:
            s = '<h1>你好</h1>'
            r1 = re.compile(r'<(?P<name1>\w+)>(\w+)</(?P=name1)>').match(s).group(2)
            print(r1)
            >>> 你好
            
    \数字 :提取的分组能够在 同一个正则中 复用  
         eg: 
             s = '<h1>你好</h1>'
             r1 = re.compile(r'<(\w+)>(\w+)</\1>')    # \1 表明复用第一个分组
             print(r1.match(s).group(2))         # 2表明提取第二个分组
             >>> 你好

匹配模式

re.M    # 多行匹配, 影响   ^ 和 $,上面讲  ^ 与 $已经详解了。
re.I    # 忽略大小写
        eg:
            s = 'aAbB'
            r1 = re.compile(r'aabb', re.I).match(s).group()
            print(r1)
            >>> aAbB

re.S    # 提高 . 的权限,  让 .  能够 匹配到换行符
        s = """
        hello
        python
        """
        r1 = re.compile(r'.*', re.S).match(s).group()    # 注意这里 re.S
        print(r1)
        >>> hello
            python
        注意:若是不写 re.S 那么 .* 只能匹配到第一行的空字符串,由于遇到第一个空行的\n就中止了
        
re.X    # 能够给正则分行写,并能够加注释,
    eg:
        import re
    
        title = '1好2你3'
        r1 = re.compile(r"""
            1     # 注释1  看这两行
            好    # 注释2  看这两行,1 和 好 没有加逗号。可是他们属于总体的规则,你能够加注释
        """, re.X)        # 把正则能够分行写,  用了re.X后,分行的正则会被看做为一行
        result = r1.match(title).group()
        print(result)    # 输出结果: 1好

贪婪模式 与 非贪婪模式

我的理解: 
    贪婪模式:(Python默认使用的就是 贪婪模式) 
        你想匹配 一个句子中的 一个单词, 可是你写的规则刚好能够 知足 匹配全部单词。
        那么它就会 贪婪的 把全部单词 所有 都给你匹配出来。   (贪)
        
        使用方法:
            * 或 +
            
    非贪婪模式:
        即便你把规则写的很好,而且能把全部字符串都匹配到, 可是若是你加上了  非贪婪模式。
        在知足规则条件的前提下,只匹配一个.
        
        使用方法:
            *? 或 +?

    eg1:基于search的贪婪模式(match同此)
        咱们先回忆一下:search()方法的 最核心思想就是:从前日后搜,搜到一个知足的就直接返回。
        OK,继续。
        
        贪婪:(默认):
            import re
            r1 = re.compile(r'\d+')
            print(r1.search('你好333你好333你好').group())
            >>> 333        # 知足规则后 尽量贪, 因此第一串连着的 '333'  搜到了就直接返回了
        
        非贪婪(就多了个问号 ? ):
            import re
            r1 = re.compile(r'\d+?')
            print(r1.search('你好333你好333你好').group())
            >>> 3          # 嗯,你的规则就是 至少一个数字,搜到了一个就能够返回了,干得漂亮。
            
    
    eg2: 基于findall的贪婪模式(若是你findall与规则,理解的不透彻,这个会有点绕的,前方高能)
        先回忆一下:findall()方法的 最核心思想就是:拿着 定死的 规则,把全部知足规则的都提出来
        OK,继续。
        
        贪婪(默认):
            import re
            r1 = re.compile(r'\d+')
            print(r1.findall('你好333你好333你好'))
            >>> ['333', '333']
            
            解释: 规则是匹配至少一位数字。
                  可是 贪婪模式 提醒了 规则:“你的任务是给我尽量的 多匹配数字”
                  findall 拿着 被贪婪化的 规则 去匹配原始字符串
                  
                  被贪婪模式 提醒过的规则果真不负众望,  一次提一串连着的 ‘333‘  
                  findall 拿着它 提取了   两次   ,就把全部数字提取出来了
                  结果就是    ['333', '333']
                  
        非贪婪:
            import re
            r1 = re.compile(r'\d+?')
            print(r1.findall('你好333你好333你好'))
            >>> ['3', '3', '3', '3', '3', '3']

            解释: 规则 一样是 匹配至少一位数字。
                  可是 非 贪婪模式 提醒了 规则:“你的任务是给我尽量的 少  匹配数字”
                  findall 拿着 被贪婪化的 规则 去匹配原始字符串
          
                  被贪婪模式 提醒过的规则果真不负众望,  一次只提取一个 ‘3‘  
                  findall 拿着它 提取了   六次   ,才把全部数字提取出来了
                  结果就是    ['3', '3', '3', '3', '3', '3']

匹配方法

match():
    '''
        match()方法是 根据规则从第一个开始,向后逐个匹配,若是有一个字符匹配不上,就返回None
    '''
    
    s = 'hello python'
    re1 = re.compile(r'he')  
    re1.match('')
    result = re1.match(s).group() if re1.match(s) else None   # 注意:非None才有group方法
    print(result)        # 经过 group()方法得到的才是最终 正则匹配的字符串
    >>> he
    
    简单分组提取:
        s = 'hello python'
        re1 = re.compile(r'h(e)llo') # 给e加个一个(),就表明添加了分组,一会要把他提出来
        result = re1.match(s).group(1) if re1.match(s) else None 
            # 注意上方的  group(1)  这个参数是1,表明 只 提取 分组 里面的内容
                >>> e
            # 若是是 group() 或 group(0)  表明提取 整个正则规则 的内容
                >>> hello
        print(result)    
        >>> e
    
    嵌套-平行(深度-广度)分组提取:
        原理:分组提取先提取嵌套的,后提取平行的 (专业点就是先深度,后广度)
        eg:
            a = '123-%%%-dd'
            result = re.compile(r'123(-(%%%)-)d(d)').match(a).groups()   
            # 或者用 group(1), group(2), group(3) 代替groups() 单个看也行
            print(result)
            >>> ('-%%%-', '%%%', 'd') 

search():
    """
        search() 方法是: 从前向后按规则‘搜索’, 直到搜到位置,搜不到就返回None
    """
    s = "aaa123aaa"
    r1 = re.compile(r'\d+').search(s).group()
    print(r1)     
    >>> 123

findall():
    """
        findall() 方法是: 按照正则规则,搜索全部符合规则的字符串,以列表的形式做为结果返回
    """
    s = "aaa---123---bbb"
    r1 = re.compile(r'\w+').findall(s)
    print(r1)
    >>> ['aaa', '123', 'bbb']
    
    微不足道的扩展:
        a = '123-%%%-dd'
        result = re.compile(r'-(.*?)-').findall(a)
        print(result)
        >>> %%%
        # 解释: findall() 方法中 若是规则中含有分组,那么就会只返回分组中提取的的内容
        
finditer():
    """
        finditer() 和 findall() 使用方式同样,只不过返回结果是 可迭代对象,easy,此处不在多说
    """
    
split():
    """
        split()方法是:按照规则去切割,切割结果以列表的方式返回
    """
    语法关联:
        咱们知道字符串  有 split() 方法,能够按照一个参数损耗来切割,可是这个参数只能指定一个
        若是让你在多种规则的前提下切割,须要怎么办。
        巧了,正则切割split() 方法就是解决这个问题的, 实例以下:
        
    s = "aaa%%123@@bbb"                  # 能够看见,%和@符号把字符分开了,如今咱们只想要字符
    r1 = re.compile(r'\W+').split(s)     # \W 大写: 以非单词性字符做为损耗规则,来切割
    print(r1)
    >>> ['aaa', '123', 'bbb']

sub():
    """
        sub()方法是: 按照规则匹配选出代替换的字符,而后本身 给定字符去替换
    """
    场景1:经常使用方式,本身给定目标字符串,按规则匹配并直接替换原始字符串
        eg:
            s = "aaa%%123@@bbb"
            r1 = re.compile(r'\W+').sub('你好',s)
            print(r1)
            >>> aaa你好123你好bbb
        
    场景2:正则匹配后的结果 通过函数操做,函数的返回值做为 替换的最终结果
        eg:
            s = "aaa%%123@@bbb"
            r1 = re.compile(r'\W+').sub(lambda a:a.group()*2, s)
            print(r1)
            >>> aaa%%%%123@@@@bbb
            解释: 按照规则匹配到的字符是 %%和@@,通过函数 乘以2后, 就替换成了 %%%%和@@@@
            
subn():
    """
        subn() 和 sub()语法几乎同样,惟一的扩展功能就是 返回结果是元组,(字符串, 次数)
    """
    s = "aaa%%123@@bbb"
    r1 = re.compile(r'\W+').subn('你好',s)
    print(r1)
    >>> ('aaa你好123你好bbb', 2)
相关文章
相关标签/搜索