Python之正則表達運用

weixin_34337265發表於2018-03-24

在python中使用正規表示式

Python 自1.5版本起增加了re 模組,它提供 Perl 風格的正規表示式模式。
re 模組使 Python 語言擁有全部的正規表示式功能。
下面主要介紹一下re模組的使用:

re.match函式

re.match 嘗試從字串的起始位置匹配一個模式,匹配成功就返回一個正規表示式匹配物件,如果不是起始位置匹配成功的話,就返回none。

函式語法:

re.match(pattern, string, flags=0)
引數 說明
pattern 正規表示式匹配模式
string 要匹配的字串
flags 標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等。

案例:

import re

username = 'jackfrued'
m = re.match(r'\w{6,20}', username)  # 從開始位置匹配長度為6到20的字母數字下劃線或者漢字
n = re.match(r'\d{6,20}', username)  # 匹配長度為6到20的數字
print(m)
print(n)
print(m.span())  # 取出匹配成功的位置,如果沒有匹配到則是None

輸出結果如下:

<_sre.SRE_Match object; span=(0, 9), match='jackfrued'> # 匹配到的正規表示式物件
None
(0, 9) 

說明:正規表示式物件的span()方法可以返回一個元組,這個元組就是正規表示式在該字串中匹配成功的位置。

re.search函式

re.search()嘗試從字串的任意位置匹配一個模式,匹配成功,則返回一個正規表示式匹配物件,否則返回None。

函式語法如下:

re.search(pattern, string, flags)

search()函式和match()的使用方法類似,唯一的區別就是match()函式只能從字串的開始位置匹配成功才返回匹配物件,否則為None,而search()可以從任意位置匹配,直到第一次匹配到。
案例:

import re

username = '###jackfrued###'
m = re.search(r'\w{6,20}', username)  # 從開始位置匹配長度為6到20的字母數字下劃線或者漢字
n = re.search(r'\W{6,20}', username)  # 匹配長度為6到20的任意非字母數字下劃線和漢字
print(m)
print(n)
print(m.span())  # 取出匹配成功的位置,如果沒有匹配到則是None

輸出結果如下:

<_sre.SRE_Match object; span=(3, 12), match='jackfrued'>
None
(3, 12)

re.findall函式

re.findall()嘗試從整個字串查詢所有滿足查詢條件的字元,並放在一個列表中返回,如果沒有匹配到則返回一個空列表。

函式使用方法與match和search類似,語法如下:

re.findall(pattern, string, flags)

案例:

import re

username = '###jackfrued###'
list1 = re.findall(r'[ion]', username)
list2 = re.findall(r'[ace]', username)
print(list1)
print(list2)

輸出結果如下:

[]
['a', 'c', 'e']

re.split函式

re.split()函式表示將字串按照一定匹配模式進行切割,切割後返回一個列表。

函式語法如下:

re.split ( pattern, string, maxsplit=0, flags=0 )
引數 說明
pattern 正規表示式匹配模式
string 要匹配的字串
maxsplit 指定最大的切割次數,預設為0,表示不限制
flags 標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等。

案例:

import re

sentence1 = '我的電話是18912901290不是18919801980'
list1 = re.split('是', sentence1)
list2 = re.split('是', sentence1, 1)
print(list1)
print(list2)

輸出結果如下:

['我的電話', '18912901290不', '18919801980']
['我的電話', '18912901290不是18919801980']

re.sub函式

re.sub()函式表示將字串按照一定匹配模式進行切割,切割後返回一個列表。

函式語法如下:

re.sub ( pattern, repl, string, count=0, flags=0 )
引數 說明
pattern 需要替換字串的正規表示式模式
repl 替換的字串
string 要匹配的字串
count 指定最大的切割次數,預設為0,表示替換所有
flags 標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等。

案例:

import re

sentence1 = '我的電話是18912901290不是18919801980'
m = re.sub(r'189', '028-', sentence1)
n = re.sub(r'189', '028-', sentence1, 1)
print(m)
print(n)

輸出結果如下:

我的電話是028-12901290不是028-19801980
我的電話是028-12901290不是18919801980

注意:repl要替換的字串,可以是一個函式,表示用函式的返回值去替換。

re.compile函式

re.compile()函式函式用於編譯正規表示式,生成一個正規表示式( Pattern )物件,給其他需要用到正規表示式物件的函式使用。

函式語法如下:

re.complie ( pattern, flags=0 )
引數 說明
pattern 需要替換字串的正規表示式模式
flags 標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等。

案例:

import re

pattern1 = re.compile(r'\d{2}')
pattern2 = re.compile(r'我')
sentence1 = '我的電話是18912901290不是18919801980'
m = re.sub(pattern1, '028-', sentence1)
list1 = re.split(pattern1, sentence1)
match_m = re.match(pattern2, sentence1)
search_m = re.search(pattern1, sentence1)
print(m)
print(list1)
print(match_m)
print(search_m)

輸出結果如下:

我的電話是028-028-028-028-028-0不是028-028-028-028-028-0
['我的電話是', '', '', '', '', '0不是', '', '', '', '', '0']
<_sre.SRE_Match object; span=(0, 1), match='我'>
<_sre.SRE_Match object; span=(5, 7), match='18'>

常用正規表示式物件的方法

引數 使用方法 解釋
match pattern.match(string, pos=0, endpos=-1) pos指定匹配開始位置,預設為o
endpos指定匹配結束位置,預設為-1
search pattern.search(string, pos=0, endpos=-1) pos指定匹配開始位置,預設為o
endpos指定匹配結束位置,預設為-1
findall pattern.findall(string, pos=0, endpos=-1) pos指定匹配開始位置,預設為o
endpos指定匹配結束位置,預設為-1
split pattern.split(string, maxsplit=0) maxsplit指定切割次數,預設為0表示不限制
sub pattern.sub(repl, string, count=0) repl表示替換的字串(可以是一個函式)
count表示匹配次數,預設為0,表示替換所有

正規表示式物件的可使用的方法其實和re模組的那幾個函式差不多,只是對於某些方法支援指定匹配的位置。

標誌位

正規表示式可以包含一些可選標誌修飾符來控制匹配的模式。修飾符被指定為一個可選的標誌。多個標誌可以通過按位 OR(|) 它們來指定。
常用的標誌修飾符見下表:

修飾符 描述
re.I 使匹配對大小寫不敏感
re.L 做本地化識別(locale-aware)匹配
re.M 多行匹配,影響 ^ 和 $
re.S 使 . 匹配包括換行在內的所有字元
re.U 根據Unicode字符集解析字元。這個標誌影響 \w, \W, \b, \B.
re.X 該標誌通過給予你更靈活的格式以便你將正規表示式寫得更易於理解。

練習一:匹配電信、移動、聯通的號碼

import re


def main():
    your_number = input('請輸入您的號碼:')
    telecom = re.compile('^1(?:[35]3|8[019]|77)\d{8}$')
    unicom = re.compile('^1(?:3[012]|5[56]|8[56]|76|45)\d{8}$')
    mobile = re.compile('^1(?:3[4-9]|5[012789]|8[23478]|47|78)\d{8}')
    test1 = re.match(unicom, your_number)
    test2 = re.match(telecom, your_number)
    test3 = re.match(mobile, your_number)
    if test1:
        print('你的號碼是聯通號碼')
    elif test2:
        print('你的號碼是電訊號碼')
    elif test3:
        print('你的號碼是移動號碼')
    else:
        print('你輸入的號碼錯誤,請重新輸入。')


if __name__ == '__main__':
    main()

練習二:將某段字串中的數字替換為當前數字的平方

import re

str1 = '我有50元錢,今天花了2兩塊坐公交,30塊錢吃飯,還剩18.'


def foo(num):
    num = num.group("name")
    num = int(num)
    return str(num ** 2)


m = re.sub(r'(?P<name>\d+)', foo, str1)
print(str1)
print(m)

程式執行結果如下:

我有50元錢,今天花了2兩塊坐公交,30塊錢吃飯,還剩18.
我有2500元錢,今天花了4兩塊坐公交,900塊錢吃飯,還剩324.

總結

re 模組的一般使用步驟如下:

  • 使用 compile 函式將正規表示式的字串形式編譯為一個 Pattern 物件;
  • 通過 Pattern 物件提供的一系列方法對文字進行匹配查詢,獲得匹配結果(一個 Match 物件);
  • 最後使用 Match 物件提供的屬性和方法獲得資訊,根據需要進行其他的操作;

Python 的正則匹配預設是貪婪匹配。

相關文章