Python 正則表達式完整示例教程

正則表達式一般用來在文本中查找和替換字符串,再簡單的文本中我們可以直接使用字符串查找,但是在大量數據和複雜結構中查找指定字符串不方便並且效率低,因此學習正則表達式顯得非常有必要。

正則表達式

元字符

正則表達式字符串是有普通字符和元字符組成。
· 普通字符,是指按照字面意義表示的字符,比如abcd。
· 元字符,是預先定義好的一些特定字符,比如下面正則表達式中的 \w 以及 . ,都屬於元字符。

rep = r'\w+@mail2\.sysu\.edu\.cn' # 匹配域名爲mail2.sysu.edu.cn的郵箱

元字符是用來描述其他字符的特殊字符,它是由基本元字符+普通元字符構成。

基本元字符:

字符 說明
\ 轉義字符
. 表示任意一個字符
+ 表示重複一次或多次
* 表示出現零次或多次
| 表示或關係,比如A
{ } 定義量詞
[ ] 定義字符類
( ) 定義分組
^ 表示取反,或匹配一行的開始
$ 匹配一行的結束
- 表示區間

\ 轉義符: 比如上面的 \. ,實際上是爲了匹配單個 . 符號,但是 . 本身又作爲元字符表示任意一個字符,因此遇到這種情況需要轉義。
^ 和 $: 這個時候不僅要求匹配字符串,而且要求字符串出現在文本的開始或者結尾,例如:

text = 'My email address is [email protected]'
rep1 = r'\w+@mail2\.sysu\.edu\.cn' # r表示原始字符,避免在正則表達式中輸入轉義
rep2 = r'^\w+@mail2\.sysu\.edu\.cn$' # 添加了^和$,對開頭結尾有要求
# \w表示任意一個字母或數字  +表示出現一次或多次

像上面這段文本,需要將郵箱提取出來的話,只能使用rep1,因爲rep2要求匹配的字符串是一行的開頭和結尾,只有在郵箱是單獨一行才能提取出來。
字符類:字符類用中括號括起來,只要其中一個字符滿足條件即可,例如:

text1 = 'I like MATLAB and Python.'
text2 = 'I like MATLAB and python.'
rep = r'[Pp]ython'  # 等效於 python1|Python
# 上述兩個文本中的python都可以用下面的正則表達式匹配出來。

^,取反符:有時候,就不需要某些字符出現,可以用取反符,例如我們需要找到非數字的字符:rep = r'^[0123456789]',這個正則表達式就可以匹配一個非數字的字符。
-,表示區間:比如上面的[0123456789],可以直接寫成[0-9],這個區間可以是分段的,比如[0-35-9],這個就表示除4以外的數字。

預定義字符

字符 說明
\. 匹配 .
\ 匹配\
\n 匹配換行
\r 匹配回車
\f 匹配翻頁符
\t 匹配水平製表符
\v 匹配垂直製表符
\s 匹配一個空格符,等價於[\t\n\r\f\v]
\S 匹配一個非空格符,等價於[^\s]
\d 匹配一個數字,等價於[0-9]
\D 匹配一個非數字,等價於[^\d]
\w 匹配任何語言單詞字符、數字、下劃線等,編碼爲ASCII的時候只能是英語
\W 等價於[^\w]

使用量詞

字符 說明
出現零次或一次
* 出現零次或多次\
+ 出現一次或多次
{n} 出現n次
{n , } 至少出現n次
{n , m} 出現n次到m次之間

貪婪量詞

默認情況都是匹配的字符串越多越好,有時候要儘可能少的匹配,就需要在後面加?,表示懶惰匹配,我們具體寫一個例子:

import re
text = '123456789'
rep1 = r'\d{5,8}' # 匹配12345678
m = re.search(rep1,text)
print(m)
rep2 = r'\d{5,8}?' # 匹配12345
m = re.search(rep2,text)
print(m)

在這裏插入圖片描述

字符分組

字符分組就是將一個子字符串可看成一個整體,進行匹配,舉個例子:

import re
text = '12312311aa'
rep = r'(123)+'  # 123出現一次或多次
rep1 = r'123+'  # 3出現一次或多次
m = re.search(rep1,text)
print(m)
m = re.search(rep2,text)
print(m)

在這裏插入圖片描述
這樣有什麼好處呢?我們舉一個具體的例子,提取一個電話號碼的區號和號碼:

import re
tel = '0715-53566663'
rep = r'(\d{3,5})-(\d{6,9})'
m = re.search(rep,tel)
print(m)
print(m.group()) # 返回匹配的所有字符串
print(m.groups()) # 返回匹配所有字符串,用元組裝起來

在這裏插入圖片描述
這樣,可以將區號和電話號碼有效分開,除此之外還可以給分組命名:

import re
tel = '0715-53566663'
rep = r'(?P<area_code>\d{3,5})-(?P<Phone_Number>\d{6,9})'
m = re.search(rep,tel)
print(m)
print(m.group()) # 返回匹配的所有字符串
print(m.groups()) # 返回匹配所有字符串,用元組裝起來
print(m.group('area_code'))  # 通過分組名稱來引用
print(m.group('Phone_Number'))

在這裏插入圖片描述

反向引用分組

我們在爬取網頁的時候,常常會出現標籤,標籤的開始和結束應該是一致的,下面舉例:

import re

text1 = '<title>Python Code</title>'
text2 = '<title>Python Code</text>'  # 這種情況是我們不想要的
rep1 = r'<(\w+)>.*</(\w+)>'
m = re.search(rep1,text1)
print(m)
m = re.search(rep1,text2) # 同樣匹配了
print(m)

在這裏插入圖片描述
對上面的代碼進行改進:

import re

text1 = '<title>Python Code</title>'
text2 = '<title>Python Code</text>'
rep1 = r'<(\w+)>.*</\1>' # 反向引用在這裏,用 \1 代替了(\w+)這個分組,表示要和前面匹配的分組相同,1代表的是分組序號
m = re.search(rep1,text1)
print(m)
m = re.search(rep1,text2)
print(m)

在這裏插入圖片描述

非捕獲分組

前面講都是捕獲分組,這些匹配的結果都被暫時存放在內存中,但是有時候我們只需要一些分組進行輔助匹配,但是不想保存,就可以使用非捕獲分組,舉一個例子,匹配.jpg文件名:

import re

text = 'im1.jpg,im2.jpg,im3.png'
rep = r'\w+(.jpg)'  (.jpg)爲捕獲分組
m = re.findall(rep,text)  # 找出所有匹配的結果
print(m)
rep = r'\w+(?:.jpg)'  (?:.jpg)爲非捕獲分組
m = re.findall(rep,text)  
print(m)

在這裏插入圖片描述
使用捕獲分組的時候,只會講捕獲分組裏面的打印出來,這並不是我們所希望的。

re模塊介紹

re 模塊是python提供的關於正則表達式的模塊,可以直接使用,下面介紹裏面的主要函數。

search()和match()函數

search()和match()函數在使用上非常相似,區別如下:

  • search從字符串中查找,返回第一個匹配對象
  • match從字符串開頭開始匹配內容,返回匹配對象
import re

text = 'My email address is [email protected].'
rep = r'\w+@mail2\.sysu\.edu\.cn' # 匹配域名爲mail2.sysu.edu.cn的郵箱
m = re.search(rep,text)
print(m)
m = re.match(rep,text)
print(m)

在這裏插入圖片描述
match與我們之前提到的 ^ 和 $ 的作用相似,一般用於驗證結果。

match對象的方法

匹配結果返回的都是一個match對象,它常用的方法包括:group(),groups(),start(),end(),span().

import re

text = 'My email address is [email protected].'
rep = r'(\w+@mail2\.sysu\.edu\.cn)' # 匹配域名爲mail2.sysu.edu.cn的郵箱
m = re.search(rep,text)
print(m)
print(m.groups())
print(m.group())
print(m.start())
print(m.end())
print(m.span())

在這裏插入圖片描述

findall()和finditer()

字符串分割和替換

分割 split()
re.split(pattern, string, count(可選) , flags (可選))
pattern是正則表達式 , string是字符串, count是最大分割次數, flags是編譯標誌

import re
p = r'\d+' # 表示至少一個數字
text = 'AB12CD23EF'
m = re.split(p,text)
print(m)

在這裏插入圖片描述
替換 sub()
re.sub(pattern, sym, text, count, flags)
pattern是正則表達式, sym是替換的字符串, text是查找的文本, count替換的次數, flags編譯標誌

import re
p = r'\d+' # 表示至少一個數字
text = 'AB12CD23EF'
m = re.sub(p, '#', text)
print(m)

在這裏插入圖片描述

編譯正則表達式

爲了能夠重複使用正則表達式,並且提高程序運行速度,可以使用編譯後正則表達式,返回一個regex對象。

import re
p = r'\d+' # 表示至少一個數字
rep = re.compile(p)  # 注意
text = 'AB12CD23EF'
m = rep.sub('#', text)  # 注意,雖然函數名一樣,但是一個是rep對象的方法,一個是re模塊中的函數
# 輸入參數也變化了
print(m)

在這裏插入圖片描述
其使用方法都是一樣的,效果也相同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章