Python 正則表達式

2020-08-11 20:40:30

作者:billy
版權宣告:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處

什麼是正則表達式

正則表達式(Regular Expression),常簡寫爲 regex 或者 RE,又稱爲規則表達式。它不是某個程式語言所特有的,而是電腦科學的一個概念,通常被用來檢索個替換符合某些規則的文字。目前,正則表達式已經在各種計算機語言(如 Java、C++ 和 Python 等)中得到了廣泛的應用和發展。

正表達式語法

  1. 行定位符:用來描述字串的邊界,‘^’ 表示行的開始,’$’ 表示行的結尾;

  2. 元字元:

程式碼 說明
. 匹配除換行符以外的任意字元
\w 匹配字母或數位或下劃線或漢字
\s 匹配任意的空白符
\d 匹配數位
\b 匹配單詞的開始或結束
^ 匹配字串的開始
$ 匹配字串的結束
  1. 重複:
限定符 說明 舉例
? 匹配前面的字元零次或一次 colou?r,該表達式可以匹配 colour 和 color
+ 匹配前面的字元一次或多次 go+gle,該表達式可以匹配的範圍從 gogle 到 goo…gle
* 匹配前面的字元零次或多次 go*gle,該表達式可以匹配的範圍從 ggle 到 goo…gle
{n} 匹配前面的字元 n 次 go{2}gle,該表達式只匹配 google
{n,} 匹配前面的字元最少 n 次 go{2,}gle,該表達式可以匹配的範圍從 google 到 goo…gle
{n,m} 匹配前面的字元最少 n 次,最多 m 次 employe{0,2},該表達式可以匹配 employ、employe 和 employee
  1. 字元類:匹配數位和字元除了可以用 ‘\d’ 和 ‘\w’ 之外,像 [aeiou] 可以匹配任意一個英文元音字母,可以輕鬆制定一個字元範圍。如果想匹配字串中任意一個漢字,可以使用 [\u4e00-\u9fa5],如果要匹配連續多個漢字,可以使用 [\u4e00-\u9fa5]+;

  2. 排除字元:’^’ 字元如果放在方括號中,表示排除的意思。例如:[^a-zA-Z]該表達式用於匹配一個不是字母的字元;

  3. 選擇字元:當包含着條件選擇的邏輯時,就需要使用選擇字元 ‘|’,該字元可以理解爲 ‘或’。例如:(^\d{15}$) | (^\d{18}$) | (^\d{17})(\d|X|x)$該字串的意思是可以匹配 15 位數位,或者 18 位數位,或者 17 位數位和最後一位(可以是數位、x 或者 X);

  4. 跳脫字元:正則表達式中的跳脫字元 ‘\’ 和 Python 字串中的跳脫字元大同小異,都是將特殊字元變爲普通字元

  5. 分組:在正則表達式中,小括號的作用有兩個,一個是改變限定符的作用範圍,還有就是分組。例如:(\.[0-9]{1,3}){3}就是對小組中內容的重複操作;

使用 re 模組實現正則表達式操作

Python 中提供了 re 模組,用於實現正則表達式的操作。使用前先匯入:import re

  1. 匹配字串
  • 使用 match() 方法進行匹配
    match() 方法用於從字串的開始處進行匹配,如果在起始位置匹配成功,則返回 Match 物件,否則返回 None,其語法格式如下:
    re.match(pattern, string, [flags])
    pattern:表示模式字串,由要匹配的正則表達式轉換而來;
    string:表示要匹配的字串;
    flags:可選參數,表示標誌位,用於控制匹配方向,如是否區分字母大小寫。常用的標誌如下表所示:
標誌 說明
A 或 ASCII 對於 \w、\W、\b、\B、\d、\D、\s 和 \S 只進行 ASCII 匹配(僅適用於 Python 3.x)
I 或 IGNORECASE 執行不區分字母大小寫的匹配
M 或 MULTILINE 將 ^ 和 $ 用於包括整個字串的開始和結尾的每一行(預設情況下,僅適用於整個字串的開始和結尾處)
S 或 DOTALL 使用 ‘.’ 字元匹配所有字元,包括換行符
X 或 VERBOSE 忽略模式字串中未跳脫的空格和註釋

範例1:

import re

pattern = r'mr_\w+'                        	 # 模式字串
string = '專案名稱:MR_SHOP mr_shop'          	 # 要匹配的字串
match = re.match(pattern, string, re.I)     	 # 匹配字串,不區分大小寫
print(match)

string = 'MR_SHOP mr_shop'
match = re.match(pattern, string, re.I)
print(match)
print('匹配值得起始位置:', match.start())
print('匹配值得結束位置:', match.end())
print('匹配位置的元組:', match.span())
print('要匹配的字串:', match.string)
print('匹配數據:', match.group())

上述例子的執行結果爲:

None
<re.Match object; span=(0, 7), match='MR_SHOP'>
匹配值得起始位置: 0
匹配值得結束位置: 7
匹配位置的元組: (0, 7)
要匹配的字串: MR_SHOP mr_shop
匹配數據: MR_SHOP

範例2:

import re

pattern = r'(13[4-9]\d{8})$|(15[01289]\d{8})$'
mobile = '13222222222'
match = re.match(pattern, mobile)
if match == None:
    print(mobile, "不是有效的中國移動手機號碼。")
else:
    print(mobile, "是有效的中國移動手機號碼。")

mobile = '15800000000'
if match == None:
    print(mobile, "不是有效的中國移動手機號碼。")
else:
    print(mobile, "是有效的中國移動手機號碼。")

上述例子的執行結果爲:

13222222222 不是有效的中國移動手機號碼。
15800000000 不是有效的中國移動手機號碼。
  • 使用 search() 方法進行匹配
    search() 方法與 match() 方法的區別在於,match 是隻在起始位置匹配,而 search 是在整個字串中搜尋,其語法格式和 match 一致,如下:
    re.search(pattern, string, [flags])

範例1:

import re

pattern = r'mr_\w+'                          	# 模式字串
string = '專案名稱:MR_SHOP mr_shop'		# 要匹配的字串
match = re.search(pattern, string, re.I)	# 匹配字串,不區分大小寫
print(match)

string = 'MR_SHOP mr_shop'
match = re.search(pattern, string, re.I)
print(match)

上述例子的執行結果爲:

<re.Match object; span=(5, 12), match='MR_SHOP'>
<re.Match object; span=(0, 7), match='MR_SHOP'>

範例2:

import re

pattern = r'(駭客)|(抓包)|(監聽)|(Trojan)'
about = '我是一名程式設計師,我喜歡看駭客方面的圖書,想研究一下 Trojan'
match = re.search(pattern, about)
if match == None:
    print(about, '@ 安全!')
else:
    print(about, '@ 出現了危險詞彙!')

about = '我是一名程式設計師,我喜歡看計算機網路方面的圖書,喜歡開發網站'
match = re.search(pattern, about)
if match == None:
    print(about, '@ 安全!')
else:
    print(about, '@ 出現了危險詞彙!')

上述例子的執行結果爲:

我是一名程式設計師,我喜歡看駭客方面的圖書,想研究一下 Trojan @ 出現了危險詞彙!
我是一名程式設計師,我喜歡看計算機網路方面的圖書,喜歡開發網站 @ 安全!
  • 使用 findall() 方法進行匹配
    findall() 方法用於在整個字串中搜尋所有符合正則表達式的字串,並以列表的形式返回。如果匹配失敗,則返回空列表,其語法格式和 match、search 一致,如下:
    re.findall(pattern, string, [flags])

範例1:

import re

pattern = r'mr_\w+'                         # 模式字串
string = '專案名稱:MR_SHOP mr_shop'         # 要匹配的字串
match = re.findall(pattern, string, re.I)   # 匹配字串,不區分大小寫
print(match)

string = 'MR_SHOP mr_shop'
match = re.findall(pattern, string)         # 匹配字串,區分大小寫
print(match)

上述例子的執行結果爲:

['MR_SHOP', 'mr_shop']
['mr_shop']

範例2:

import re

pattern1 = r'[1-9]{1,3}(\.[0-9]{1,3}){3}'
str = '127.0.0.1 192.168.1.66'
match = re.findall(pattern1, str)
print(match)	

pattern1 = r'([1-9]{1,3}(\.[0-9]{1,3}){3})'
match = re.findall(pattern1, str)
print(match)

for item in match:
    print(item[0])

上述例子的執行結果爲:

['.1', '.66']
[('127.0.0.1', '.1'), ('192.168.1.66', '.66')]
127.0.0.1
192.168.1.66

注意:如果模式字串中出現分組,那麼得到的結果是根據分組進行匹配的結果。如果想獲取整個模式字串的匹配,可以將整個模式字串使用一對小括號進行分組。然後在獲取結果時,只取返回值列表的每個元素的第一個元素。

  1. 替換字串
    sub() 方法用於時顯示字串替換。其語法格式如下:
    re.sub(pattern, repl, string, count, flags)
    pattern:表示模式字串,由要匹配的正則表達式轉換而來;
    repl:表示替換的字串;
    string:表示要被查詢替換的原始字串;
    count:可選參數,表示模式匹配後替換的最大次數;
    flags:可選參數,表示標誌位,用於控制匹配方式,如是否區分字母大小寫;

範例:

import re

pattern = r'1[34578]\d{9}'
string = '中獎號碼爲:84978981 聯繫電話爲:13611111111'
result = re.sub(pattern, '1XXXXXXXXXX', string)     	# 隱藏字串中的手機號
print(result)

pattern = r'(駭客)|(抓包)|(監聽)|(Trojan)'
about = '我是一名程式設計師,我喜歡看駭客方面的圖書,想研究一下 Trojan'
sub = re.sub(pattern, '@__@', about)			# 替換出現的危險字元
print(sub)

上述例子的執行結果爲:

中獎號碼爲:84978981 聯繫電話爲:1XXXXXXXXXX
我是一名程式設計師,我喜歡看@__@方面的圖書,想研究一下 @__@
  1. 使用正則表達式分割字串
    split() 方法用於實現根據正則表達式分割字串,並以列表的形式返回。其作用與字串物件的 split() 方法類似,所不同的就是分割字元由模式字串指定,其語法格式如下:
    re.split(pattern, string, [maxsplit], [flags])

範例:

import re

str = '@馬雲 @馬化騰 @劉強東'
pattern = r'\s*@'
list = re.split(pattern, str)
print('我的好友有:')
for item in list:
    if item != "":
        print(item)

上述例子的執行結果爲:

我的好友有:
馬雲
馬化騰
劉強東