經驗拾憶(純手工)=> 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)
相關文章
相關標籤/搜索