Python學習筆記 - 正規表示式

MADAO是不會開花的發表於2019-01-16

Python中正規表示式相關的都在re模組中。簡單整理一下常見的語法和方法

  • 關於轉義字元

    如果執行下面了下面這句程式碼:

    print('a\nb')

    那麼會得到這樣的結果:

    Python學習筆記 - 正規表示式

    並沒有列印出\n只有a和b,而且它們還換行了。如果想要列印\n這個字串有兩種辦法:

    print('a\\nb')
    print(r'a\nb')
    複製程式碼

    Python學習筆記 - 正規表示式

    第一種就是再加一個轉義符號(\)將原本的轉義符轉義成原本的意思。第二種是使用r'字串'這種格式。推薦用第二種。

  • re.match 和 re.search

    re.match 和 re.search很像,它們都用於判斷匹配是否成功,如果成功就返回一個物件,不成功就返回None

    import re
    
    res_match = re.match(r'ab', 'ababababab')
    res_search = re.search(r'ab', 'ababababab')
    
    print(res_match) # <re.Match object; span=(0, 2), match='ab'>
    print(res_search) # <re.Match object; span=(0, 2), match='ab'>
    複製程式碼

    它們兩的區別在於,如果字串的開頭就匹配失敗,match方法會直接返回None,search則會繼續匹配下去。例子:

    import re
    
    res_match = re.match(r'ab', 'ccccababababab')
    res_search = re.search(r'ab', 'ccccbababababab')
    
    print(res_match)  # None
    print(res_search) # <re.Match object; span=(5, 7), match='ab'>
    複製程式碼

    match和search方法返回的物件中span表示匹配成功的字元的位置,match則是匹配結果,它們返回的物件都有group和groups方法。

    直接看例子:

    import re
    
    res_match = re.match(r'(ab)-(cd)-(ef)', 'ab-cd-ef')
    
    
    print('group不帶引數:', res_match.group())
    print('group帶引數:', res_match.group(1))
    print('group帶引數:', res_match.group(2))
    print('group帶引數:', res_match.group(3))
    print('group帶多個引數:', res_match.group(1, 2, 3))
    
    print('groups:', res_match.groups())
    複製程式碼

    結果:

    Python學習筆記 - 正規表示式

    group和groups方法會返回匹配到的字元,如果在正規表示式中用了()那麼表示匹配括號內的所有內容,一個()就是一個組, group方法接受的引數就是組的序號。組從1開始。

  • re.compile

    compile方法用於建立一個正規表示式( Pattern )物件

    prog = re.compile(pattern)
    result = prog.match(string)
    複製程式碼

    等價於

    result = re.match(pattern, string)
    複製程式碼

    例子:

    import re
    reg = re.compile(r'\d')
    
    res_match = reg.match('12313131')
    res_search = reg.search('abcdefg12313131')
    
    print(res_match.group()) # 1
    print(res_search.group()) # 1
    複製程式碼

    可以看到上面例子中數字有很多個,但是隻匹配到一個就不匹配了。如果想要匹配所有符合規則的字串可以用findAll方法,例子:

    import re
    reg = re.compile(r'\d')
    
    res_match = reg.match('12313131')
    res_search = reg.search('abcdefg12313131')
    res_findAll = reg.findall('a1h2h1312h31hjg31j3')
    
    print(res_match.group()) # 1
    print(res_search.group()) # 1
    print(res_findAll)  # ['1', '2', '1', '3', '1', '2', '3', '1', '3', '1', '3']
    複製程式碼
  • re.sub

    re.sub用於替換字串中的匹配項。它的語法是:

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

    • pattern : 正則中的模式字串。
    • repl : 替換的字串,也可為一個函式。
    • string : 要被查詢替換的原始字串。
    • count : 模式匹配後替換的最大次數,預設 0 表示替換所有的匹配。

    例子:

    import re
    test_str = '2012-12-21'
    
    def square(num):
        return str(int(num.group())**2)
        
    
    res = re.sub(r'\D', '/', test_str)
    res_func = re.sub(r'\d', square, test_str)
    
    print(res) # 2012/12/21
    print(res_func) # 4014-14-41
    複製程式碼
  • 貪婪模式

    在說貪婪模式之前,先介紹幾個特殊字元:*, +, ?

    • *: 匹配0到任意次
    • +: 匹配1到任意次
    • ?: 匹配0到1次

    例子:

    import re
    reg = re.compile(r'ab*')
    reg_1 = re.compile(r'ab+')
    reg_2 = re.compile(r'ab?')
    
    test_str = 'abbbbbbbbbbbbbb'
    
    res_xinghao = reg.match(test_str)
    res_jiahao = reg_1.match(test_str)
    res_wenhao = reg_2.match(test_str)
    
    print('*:', res_xinghao.group()) # *: abbbbbbbbbbbbbb
    print('+:', res_jiahao.group())  # +: abbbbbbbbbbbbbb
    print('?:', res_wenhao.group())  # ?: ab
    複製程式碼

    *, +, ? 它們都是貪婪模式,也是就在匹配成功的情況下,儘可能的多匹配符合規則的字元。

    如果想要非貪婪模式那麼只需要在它們後面各自加上?即可:*?, +?, ??

    import re
    reg = re.compile(r'ab*?')
    reg_1 = re.compile(r'ab+?')
    reg_2 = re.compile(r'ab??')
    
    test_str = 'abbbbbbbbbbbbbb'
    
    res_xinghao = reg.match(test_str)
    res_jiahao = reg_1.match(test_str)
    res_wenhao = reg_2.match(test_str)
    
    print('*?:', res_xinghao.group())  # *?: a
    print('+?:', res_jiahao.group())   # +?: ab
    print('??:', res_wenhao.group())   # ??: a
    複製程式碼

正規表示式還有很多的特殊字元,也叫元字元。官方文件解釋的更清楚,這裡就不寫了。它們的組合很多,這也是我覺得正則難的原因。

相關文章