Python3標准庫(二) re模塊


原網址:https://blog.csdn.net/lisonglisonglisong/article/details/39697137

 

正則表達式(Regular Expression)是字符串處理的常用工具,通常被用來檢索、替換那些符合某個模式(Pattern)的文本。很多程序設計語言都支持正則表達式,像Perl、Java、C/C++。在 Python 中是通過標准庫中的re 模塊 提供對正則的支持。

 

一、正則表達式介紹

在使用 re 模塊之前,先來了解一下正則表達式的基本語法。

1)用途

通過使用正則表達式,可以:

  • 測試字符串內的模式。—— 例如,可以測試輸入字符串,以查看字符串內是否出現電話號碼模式或信用卡號碼模式。這稱為數據驗證。

  • 替換文本。—— 可以使用正則表達式來識別文檔中的特定文本,完全刪除該文本或者用其他文本替換它。

  • 基於模式匹配從字符串中提取子字符串。—— 可以查找文檔內或輸入域內特定的文本。

2)語法

本文主要介紹正則的基本語法以及 re 模塊的使用,不包括如何編寫高效的正則表達式、如何優化正則表達式,這些主題請看其他教程。

 

下圖列出了Python支持的一些正則表達式元字符和語法:

3)貪婪模式與非貪婪模式

“貪婪模式”總是嘗試匹配盡可能多的字符;“非貪婪模式”則相反,總是匹配盡可能少的字符。例如,用"ab*"如果用於查找"abbbc",將找到"abbb"。而如果使用非貪婪的數量詞"ab*?",將找到"a"。

 

二、使用 re 模塊

下面我們開始來使用 re 模塊。

1)編譯正則表達式

re 模塊提供了 re.compile() 函數將一個字符串編譯成 pattern object,用於匹配或搜索。函數原型如下:

re.compile(pattern, flags=0)

re.compile() 還接受一個可選的參數 flag,用於指定正則匹配的模式。關於匹配模式,后面將會講到。

p = re.compile('ab*', re.IGNORECASE)

 

2)反斜杠的困擾

在 python 的字符串中,\ 是被當做轉義字符的。在正則表達式中,\ 也是被當做轉義字符。這就導致了一個問題:如果你要匹配 \ 字符串,那么傳遞給 re.compile() 的字符串必須是"\\\\"。

由於字符串的轉義,所以實際傳遞給 re.compile() 的是"\\",然后再通過正則表達式的轉義,"\\" 會匹配到字符"\"。這樣雖然可以正確匹配到字符 \,但是很麻煩,而且容易漏寫反斜杠而導致 Bug。那么有什么好的解決方案呢?

原始字符串很好的解決了這個問題,通過在字符串前面添加一個r,表示原始字符串,不讓字符串的反斜杠發生轉義。那么就可以使用r"\\"來匹配字符\了。

3)pattern object 執行匹配

一旦你編譯得到了一個 pattern object,你就可以使用 pattern object 的方法或屬性進行匹配了,下面列舉幾個常用的方法,更多請看這里

regex.match(string[, pos[, endpos]])

  • 匹配從 pos 到 endpos 的字符子串的開頭。匹配成功返回一個 match object,不匹配返回 None。
  • pos 的默認值是0,endpos 的默認值是 len(string),所以默認情況下是匹配整個字符串的開頭。

 

import re
pattern = re.compile("ar{1}")
print(pattern.match("army")) # "ar"在開頭,匹配成功
print(pattern.match("mary")) # "ar"不在開頭,匹配失敗
print(pattern.match("mary", 1)) # "ar"不在開頭,但在子串的開頭
# 輸出結果:
# <_sre.SRE_Match object; span=(0, 2), match='ar'>
# None
# <_sre.SRE_Match object; span=(1, 3), match='ar'>

  

 

regex.search(string[, pos[, endpos]])

  • 掃描整個字符串,並返回它找到的第一個匹配(Match object)。
  • 和 regex.match() 一樣,可以通過 pos 和 endpos 指定范圍。

 

pattern = re.compile("ar{1}")
match = pattern.search("mary") # search
print(match)
# 輸出結果:
# <_sre.SRE_Match object; span=(1, 3), match='ar'>

 

 

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

  • 找到所有匹配的子串,並返回一個 list 。
  • 可選參數 pos 和 endpos 和上面一樣。
pattern = re.compile(r"\d+")
lst = pattern.findall("abc1def2rst3xyz") # findall
print(lst)
# 輸出結果:
# ['1', '2', '3']

  

regex.finditer(string[, pos[, endpos]])

  • 找到所有匹配的子串,並返回由這些匹配結果(match object)組成的迭代器。
  • 可選參數 pos 和 endpos 和上面一樣。
pattern = re.compile(r"\d+")
p = pattern.finditer("abc1def2rst3xyz")
for i in p:
print(i)
# 輸出結果:
# <_sre.SRE_Match object; span=(3, 4), match='1'>
# <_sre.SRE_Match object; span=(7, 8), match='2'>
# <_sre.SRE_Match object; span=(11, 12), match='3'>

  

4)match object 獲取結果

在上面講到,通過 pattern object 的方法(除 findall 外)進行匹配得到的返回結果都是 match object。每一個 match object 都包含了匹配到的相關信息,比如,起始位置、匹配到的子串。那么,我們如何從 match object 中提取這些信息呢?

match object 提供了一些方法,下面列舉幾個常用的方法,更多請看這里

match.group([group1, ...])

  • 返回 match object 中的字符串。
  • 每一個 ( ) 都是一個分組,分組編號從1開始,從左往右,每遇到一個左括號,分組編號+1。
  • 組 0 總是存在的,它就是整個表達式 。
  • 沒有參數時,group1默認為0,這時返回整個匹配到的字符串。
  • 指定一個參數(整數)時,返回該分組匹配到的字符串。
  • 指定多個參數時,返回由那幾個分組匹配到的字符串組成的 tuple。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m) # <_sre.SRE_Match object; span=(0, 11), match='Kobe Bryant'>
print(m.group()) # Kobe Bryant
print(m.group(1)) # Kobe
print(m.group(2)) # Bryant
print(m.group(1, 2)) # ('Kobe', 'Bryant')

  

match.groups()

  • 返回由所有分組匹配到的字符串組成的 tuple。
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')

  

match.start([group])

  • 沒有參數時,返回匹配到的字符串的起始位置。
  • 指定參數(整數)時,返回該分組匹配到的字符串的起始位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.start()) # 0
print(m.start(2)) # 5

  

match.end([group])

  • 沒有參數時,返回匹配到的字符串的結束位置。
  • 指定參數(整數)時,返回該分組匹配到的字符串的結束位置。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.end()) # 11
print(m.end(1)) # 4

  

match.span([group])

  • 返回一個二元 tuple 表示匹配到的字符串的范圍,即 (start, end)。
  • 指定參數時,返回該分組匹配到的字符串的 (start, end)。
pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
print(m.span()) # (0, 11)
print(m.span(2)) # (5, 11)

  

5)模塊級別的函數

上面講到的函數都是對象的方法,要使用它們必須先得到相應的對象。本節將介紹一些Module-Level Functions,比如 match(),search(),findall() 等等。你不需要創建一個 pattern object 就可以直接調用這些函數。

re.compile(pattern, flags=0):上面已經介紹過。

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

pattern = re.compile(r"(\w+) (\w+)")
m = pattern.match("Kobe Bryant, Lakers")
# 相當於
m = re.match(r"(\w+) (\w+)","Kobe Bryant, Lakers")

  

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

pattern = re.compile(r"(\w+) (\w+)")
m = pattern.search("Kobe Bryant, Lakers")
# 相當於
m = re.search(r"(\w+) (\w+)","Kobe Bryant, Lakers")

 

re.findall(pattern, string, flags=0):與上面類似。

re.finditer(pattern, string, flags=0):與上面類似。

6)編譯標志(匹配模式)

在講 re.compile() 函數時,曾說到該函數還接受可選的第二個參數,用以設置匹配模式。可選的匹配模式有:

  • re.IGNORECASE:忽略大小寫,同 re.I。

  • re.MULTILINE:多行模式,改變^和$的行為,同 re.M。

  • re.DOTALL:點任意匹配模式,讓'.'可以匹配包括'\n'在內的任意字符,同 re.S。

  • re.LOCALE:使預定字符類 \w \W \b \B \s \S 取決於當前區域設定, 同 re.L。

  • re.ASCII:使 \w \W \b \B \s \S 只匹配 ASCII 字符,而不是 Unicode 字符,同 re.A。

  • re.VERBOSE:詳細模式。這個模式下正則表達式可以是多行,忽略空白字符,並可以加入注釋。主要是為了讓正則表達式更易讀,同re.X。例如,以下兩個正則表達式是等價的:

a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

 

三、修改字符串

第二部分講的是字符串的匹配和搜索,但是並沒有改變字符串。下面就講一下可以改變字符串的操作。

1)分割字符串

split()函數在匹配的地方將字符串分割,並返回一個 list。同樣的,re 模塊提供了兩種 split 函數,一個是 pattern object 的方法,一個是模塊級的函數。

regex.split(string, maxsplit=0)

  • maxsplit用於指定最大分割次數,不指定將全部分割。
pattern = re.compile(r"[A-Z]+")
m = pattern.split("abcDefgHijkLmnoPqrs")
print(m)
# 輸出結果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']

  

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

  • 模塊級函數,功能與 regex.split() 相同。
  • flags用於指定匹配模式。
m = re.split(r"[A-Z]+","abcDefgHijkLmnoPqrs")
print(m)
# 輸出結果:
# ['abc', 'efg', 'ijk', 'mno', 'qrs']

  

2)搜索與替換

另一個常用的功能是找到所有的匹配,並把它們用不同的字符串替換。re 模塊提供了sub()subn()來實現替換的功能,而它們也分別有自己兩個不同版本的函數。

regex.sub(repl, string, count=0)

  • 使用 repl 替換 string 中每一個匹配的子串,返回替換后的字符串。若找不到匹配,則返回原字符串。
  • repl 可以是一個字符串,也可以是一個函數。
  • 當repl是一個字符串時,任何在其中的反斜杠都會被處理。
  • 當repl是一個函數時,這個函數應當只接受一個參數(Match對象),並返回一個字符串用於替換。
  • count 用於指定最多替換次數,不指定時全部替換。
def fun(m):
return m.group().upper()
pattern = re.compile(r"like", re.I)
s1 = pattern.sub(r"love", "I like you, do you like me?")
s2 = pattern.sub(fun, "I like you, do you like me?")
print(s1)
print(s2)
# 輸出結果:
# I love you, do you love me?
# I LIKE you, do you LIKE me?

  

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

  • 模塊級函數,與 regex.sub() 函數功能相同。
  • flags 用於指定匹配模式。

regex.subn(repl, string, count=0)

  • 同 sub(),只不過返回值是一個二元 tuple,即(sub函數返回值, 替換次數)

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

    • 模塊級函數,功能同 regex.subn()。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM