Python3 正則表達式

正則表達式是一種用來匹配字符串的強有力的武器。它的設計思想是用一種描述性的語言來給字符串定義一個規則,凡是符合規則的字符串,咱們就認爲它「匹配」了,不然,該字符串就是不合法的。html

re 模塊使 Python 語言擁有所有的正則表達式功能。python

compile 函數根據一個模式字符串和可選的標誌參數生成一個正則表達式對象。該對象擁有一系列方法用於正則表達式匹配和替換。git

re 模塊也提供了與這些方法功能徹底一致的函數,這些函數使用一個模式字符串作爲它們的第一個參數。github

咱們主要先學習一下經常使用的正則表達式處理函數。正則表達式

re.match 函數

語法格式數據庫

re.match(pattern, string, flags=0)

pattern -- 匹配的正則表達式
string  -- 要匹配的字符串
flags   -- 標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等

匹配成功 re.match 方法返回一個匹配的對象,不然返回 None 。express

咱們可使用 group(num) 或 groups() 匹配對象函數來獲取匹配表達式。函數

group(num=0) -- 匹配的整個表達式的字符串
group() 能夠一次輸入多個組號,在這種狀況下它將返回一個包含那些組所對應值的元組

groups()     -- 返回一個包含全部小組字符串的元組,從 1 到 所含的小組號。

re.match 嘗試從字符串的起始位置匹配一個模式,若是不是起始位置匹配成功的話,match()就返回none。學習

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re

# 在起始位置匹配,只返回一個結果
print(re.match('www', 'www.zhouyuyao.cn'))
# 結果 —— <_sre.SRE_Match object; span=(0, 3), match='www'>

# 在起始位置匹配,過濾掉一些信息,只留位置,返回元組
print(re.match('www', 'www.zhouyuyao.cn').span())
# 結果 —— (0, 3)

# 在起始位置匹配,返回字符串
print(re.match('www', 'www.zhouyuyao.cn').group(0)) # 默認爲 0
# 結果 —— www

# 不在起始位置匹配
print(re.match('cn', 'www.zhouyuyao.cn'))
# 結果 —— None

 

正則表達式模式

模式字符串使用特殊的語法來表示一個正則表達式:google

字母和數字表示他們自身。一個正則表達式模式中的字母和數字匹配一樣的字符串。

多數字母和數字前加一個反斜槓時會擁有不一樣的含義。

標點符號只有被轉義時才匹配自身,不然它們表示特殊的含義。

反斜槓自己須要使用反斜槓轉義。

因爲正則表達式一般都包含反斜槓,因此你最好使用原始字符串來表示它們。模式元素(如 r'/t',等價於'//t')匹配相應的特殊字符。

模式 描述
^ 匹配字符串的開頭
$ 匹配字符串的末尾。
. 匹配任意字符,除了換行符,當re.DOTALL標記被指定時,則能夠匹配包括換行符的任意字符。
[...] 用來表示一組字符,單獨列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c以外的字符。
re* 匹配0個或多個的表達式。
re+ 匹配1個或多個的表達式。
re? 匹配0個或1個由前面的正則表達式定義的片斷,非貪婪方式
re{ n}  
re{ n,} 精確匹配n個前面表達式。
re{ n, m} 匹配 n 到 m 次由前面的正則表達式定義的片斷,貪婪方式
a| b 匹配a或b
(re) G匹配括號內的表達式,也表示一個組
(?imx) 正則表達式包含三種可選標誌:i, m, 或 x 。隻影響括號中的區域。
(?-imx) 正則表達式關閉 i, m, 或 x 可選標誌。隻影響括號中的區域。
(?: re) 相似 (...), 可是不表示一個組
(?imx: re) 在括號中使用i, m, 或 x 可選標誌
(?-imx: re) 在括號中不使用i, m, 或 x 可選標誌
(?#...) 註釋.
(?= re) 前向確定界定符。若是所含正則表達式,以 ... 表示,在當前位置成功匹配時成功,不然失敗。但一旦所含表達式已經嘗試,匹配引擎根本沒有提升;模式的剩餘部分還要嘗試界定符的右邊。
(?! re) 前向否認界定符。與確定界定符相反;當所含表達式不能在字符串當前位置匹配時成功
(?> re) 匹配的獨立模式,省去回溯。
\w 匹配字母數字
\W 匹配非字母數字
\s 匹配任意空白字符,等價於 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意數字,等價於 [0-9].
\D 匹配任意非數字
\A 匹配字符串開始
\Z 匹配字符串結束,若是是存在換行,只匹配到換行前的結束字符串。c
\z 匹配字符串結束
\G 匹配最後匹配完成的位置。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 能夠匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等. 匹配一個換行符。匹配一個製表符。等
\1...\9 匹配第n個分組的子表達式。
\10 匹配第n個分組的子表達式,若是它經匹配。不然指的是八進制字符碼的表達式。

 

正則表達式修飾符(可選標誌)

正則表達式能夠包含一些可選標誌修飾符來控制匹配的模式。修飾符被指定爲一個可選的標誌。多個標誌能夠經過按位 OR( | ) 它們來指定。如 re.I | re.M 被設置成 I 和 M 標誌:

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

下面經過一個例子來控制匹配的模式

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re

line = "You have never giveup"

Obj = re.match(r'(.*) have (.*?) .*', line, re.M | re.I)
# re.M     多行匹配,影響 ^ 和 $
# re.I     使匹配對大小寫不敏感

if Obj:
    print("Obj.group() : ", Obj.group())
    print("Obj.group(1) : ", Obj.group(1))
    print("Obj.group(2) : ", Obj.group(2))
else:
    print("No Obj!")

 

re.search 方法

re.search 的語法與 re.match 同樣,可是 re.search 是掃描整個字符串並返回第一個成功的匹配。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re

# 在起始位置匹配,只返回一個結果
print(re.search('www', 'www.zhouyuyao.cn'))
# 結果 <_sre.SRE_Match object; span=(0, 3), match='www'>

# 在起始位置匹配,span 過濾掉一些信息,只留位置,返回元組
print(re.search('www', 'www.zhouyuyao.cn').span())
# 結果 (0, 3)

# 在起始位置匹配,返回字符串
print(re.search('www', 'www.zhouyuyao.cn').group(0))
# 結果 www

# 不在起始位置匹配
print(re.search('cn', 'www.zhouyuyao.cn'))
# 結果 <_sre.SRE_Match object; span=(14, 16), match='cn'>

# 不在起始位置匹配,span 過濾掉一些信息,只留位置,返回元組
print(re.search('cn', 'www.zhouyuyao.cn').span())
# 結果 (14, 16)

 

re.match 與 re.search 的區別

re.match 只匹配字符串的開始,若是字符串開始不符合正則表達式,則匹配失敗,函數返回 None;而re.search 匹配整個字符串,直到找到一個匹配。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 15:26
# @Author  : zhouyuyao
# @File    : demon3.py

import re

line = "You have never giveup"
# re.match只匹配字符串的開始,若是字符串開始不符合正則表達式,則匹配失敗,函數返回None
matchObj = re.match(r'never', line, re.M | re.I)
if matchObj:
    print("match --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")

# re.search匹配整個字符串,直到找到一個匹配
matchObj = re.search(r'never', line, re.M | re.I)
if matchObj:
    print("search --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")

 

檢索和替換

Python 的re模塊提供了re.sub用於替換字符串中的匹配項,其語法以下

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

pattern —— 正則中的模式字符串
repl    —— 替換的字符串,也可爲一個函數
string  —— 要被查找替換的原始字符串
count   —— 模式匹配後替換的最大次數,默認 0 表示替換全部的匹配

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 15:36
# @Author  : zhouyuyao
# @File    : demon4.py

import re

phone = "0731-2734-538 # 這是一個電話號碼"

# 第一種 刪除註釋
num = re.sub(r'#.*$', "", phone)
# .	    匹配任意字符,除了換行符,當re.DOTALL標記被指定時,則能夠匹配包括換行符的任意字符
# $	    匹配字符串的末尾。
# re*	匹配0個或多個的表達式

print("去掉#號後面的字符串的電話號碼爲 : ", num)
# 結果 去掉#號後面的字符串的電話號碼爲 :  0731-2734-538 


# 第二種 移除非數字的內容
num = re.sub(r'\D',"", phone)
# num = re.sub(r'\D',"", phone)
# \D    匹配任意非數字

print("移除非數字的內容後的電話號碼 : ",num)
# 結果 移除非數字的內容後的電話號碼 :  07312734538

 

compile 函數

compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用,語法格式爲

re.compile(pattern[, flags])

pattern —— 一個字符串形式的正則表達式
flags   —— 可選,表示匹配模式,好比忽略大小寫,多行模式等,具體參數爲:
re.I    —— 忽略大小寫
re.L    —— 表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境
re.M    —— 多行模式
re.S    —— 即爲' . '而且包括換行符在內的任意字符(' . '不包括換行符)
re.U    —— 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依賴於 Unicode 字符屬性數據庫
re.X    —— 爲了增長可讀性,忽略空格和' # '後面的註釋

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 16:37
# @Author  : zhouyuyao
# @File    : demon5.py

import re
pattern = re.compile(r'\d+')                    # 用於匹配至少一個數字
m = pattern.match('one12twothree34four')        # 查找頭部,沒有匹配
print(m)
# 結果 None

m = pattern.match('one12twothree34four', 2, 10) # 從'e'的位置開始匹配,沒有匹配
print(m)
# 結果 None

m = pattern.match('one12twothree34four', 3, 10) # 從'1'的位置開始匹配,正好匹配
print(m)                                        # 返回一個 Match 對象
# 結果 <_sre.SRE_Match object; span=(3, 5), match='12'>

print(m.group(0))   # 可省略 0
# 結果 12

print(m.start(0))   # 可省略 0
# 結果 3

print(m.end(0))     # 可省略 0
# 結果 5

print(m.span(0))    # 可省略 0
# 結果 (3, 5)

在上面,當匹配成功時返回一個 Match 對象,其中:
group([group1, …]) —— 方法用於得到一個或多個分組匹配的字符串,當要得到整個匹配的子串時,可直接使用 group() 或 group(0);

start([group])         —— 方法用於獲取分組匹配的子串在整個字符串中的起始位置(子串第一個字符的索引),參數默認值爲 0;

end([group])          —— 方法用於獲取分組匹配的子串在整個字符串中的結束位置(子串最後一個字符的索引+1),參數默認值爲 0;

span([group])        —— 方法返回 (start(group), end(group))。
 

findall

在字符串中找到正則表達式所匹配的全部子串,並返回一個列表,若是沒有找到匹配的,則返回空列表。

注意: match 和 search 是匹配一次, findall 匹配全部。

語法格式爲:

findall(string[, pos[, endpos]])

參數:
string —— 待匹配的字符串
pos    —— 可選參數,指定字符串的起始位置,默認爲 0
endpos —— 可選參數,指定字符串的結束位置,默認爲字符串的長度

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 16:45
# @Author  : zhouyuyao
# @File    : demon6.py
import re

pattern = re.compile(r'\d+')  # 查找數字,匹配1個或多個的數字
result1 = pattern.findall('zyy 123 google 456')
result2 = pattern.findall('z88hou123yuyao456', 0, 10)

print(result1)
# 結果 ['123', '456']

print(result2)
# 結果 ['88', '12']

 

re.finditer

和 findall 相似,在字符串中找到正則表達式所匹配的全部子串,並把它們做爲一個迭代器返回。

re.finditer(pattern, string, flags=0)

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 16:45
# @Author  : zhouyuyao
# @File    : demon6.py

import re

it = re.finditer(r"\d+", "12a32bc43jf3")
for match in it:
    print(match.group())

 

re.split

split 方法按照可以匹配的子串將字符串分割後返回列表,它的使用形式以下:

re.split(pattern, string[, maxsplit=0, flags=0])

pattern	 —— 匹配的正則表達式
string	 —— 要匹配的字符串
maxsplit —— 分隔次數,maxsplit=1 分隔一次,默認爲 0,不限制次數
flags	 —— 標誌位,用於控制正則表達式的匹配方式,即正則表達式修飾符,如:是否區分大小寫,多行匹配等等

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2018/5/1 16:52
# @Author  : zhouyuyao
# @File    : demon7.py
import re

print(re.split('\w+', 'zhouyuyao, zhouyuyao, zhouyuyao.'))
# \w  小寫w,匹配數字、字母、下劃線
# 結果 ['', ', ', ', ', '.']

print(re.split('(\W+)', ' zhouyuyao, zhouyuyao, zhouyuyao.'))
# \W  大寫W,匹配非數字、字母、下劃線
# 結果 ['', ' ', 'zhouyuyao', ', ', 'zhouyuyao', ', ', 'zhouyuyao', '.', '']

print(re.split('\W+', ' zhouyuyao, zhouyuyao, zhouyuyao.', 1))
# 結果 ['', 'zhouyuyao, zhouyuyao, zhouyuyao.']

print(re.split('a.*', 'hello world'))  # 對於一個找不到匹配的字符串而言,split 不會對其做出分割
# 結果 ['hello world']

 

 

 

 

參考資料:

1. http://www.runoob.com/python3/python3-reg-expressions.html

2. https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143193331387014ccd1040c814dee8b2164bb4f064cff000

3. https://github.com/michaelliao/learn-python3/blob/master/samples/regex/regex.py

4. https://blog.csdn.net/u014467169/article/details/51345657

相關文章
相關標籤/搜索