在上一篇文章中,我們介紹了 Python 的字元類和對元字元進行了深入講解,現在我們介紹 Python 的捕獲組和特殊匹配字串。檢視上一篇文章請點選:https://www.cnblogs.com/dustman/p/10036661.html
捕獲組
可以通過用括號包圍正規表示式的部分來建立組,意味著一個組可以作為元字元 (例如 * 和 ?) 的引數。
import re
pattern = r"python(ice)*"
string1 = "python!"
string2 = "ice"
string3 = "pythonice"
match1 = re.match(pattern,string1)
match2 = re.match(pattern,string2)
match3 = re.match(pattern,string3)
if match1:
print(match1.group())
print("match 1")
if match2:
print(match2.group())
print("match 2")
if match3:
print(match3.group())
print("match 3")
執行結果:
>>>
python
match 1
pythonice
match 3
>>>
上面的例子 (ice) 表示捕獲組。
之前介紹元字元和字元類時,我們都用到了 group 函式訪問捕獲組中的內容。group(0) 或 group() 返回全部匹配,group(n) 呼叫 n 大於 0 返回第 n 組匹配。groups() 返回一個包含所有捕獲組的元組。
import re
pattern = r"j(av)(ap)(yt(h)o)n"
string = "javapythonhtmlmysql"
match = re.match(pattern,string)
if match:
print(match.group())
print(match.group(0))
print(match.group(1))
print(match.group(2))
print(match.groups())
執行結果:
>>>
javapython
javapython
av
ap
(`av`, `ap`, `ytho`, `h`)
>>>
捕獲組同時可以巢狀,也就是說一個組可以是另一個組的子集。
有一些特殊的捕獲組,它們叫非捕獲組和命名捕獲組。
命名捕獲組的格式是 (?p<name>…),其中 name 是組的名稱,…是要匹配的表示式。它們的行為與正常組完全相同,除了可以通過索引訪問還可以通過 group(name) 方式訪問它們。
非捕獲組的格式是 (?:…)。非捕獲組值匹配結果,但不捕獲結果,也不會分配組號,當然也不能在表達式和程式中做進一步處理。
import re
pattern = r"(?P<python>123)(?:456)(789)"
string = "123456789"
match = re.match(pattern,string)
if match:
print(match.group("python"))
print(match.groups())
執行結果:
>>>
123
(`123`, `789`)
>>>
或匹配的元字元 |,red|blue 表示匹配 red 或者 blue。
import re
string1 = "python"
string2 = "pyihon"
string3 = "pylhon"
pattern = r"py(t|i)hon"
match1 = re.match(pattern,string1)
match2 = re.match(pattern,string2)
match3 = re.match(pattern,string3)
if match1:
print(match1.group())
print("match 1")
if match2:
print(match2.group())
print("match 2")
if match3:
print(match3.group())
print("match 3")
執行結果:
>>>
python
match 1
pyihon
match 2
>>>
特殊匹配字串
特殊序列
在正規表示式中可以使用各種的捕獲組序列。它們被寫成反斜槓,後面跟著另一個數字字元。
特殊序列是一個反斜槓和一個介於 1 到 99 之間的數字,比如:1。數字自發表示捕獲組的序列,也就是說我們可以在正規表示式裡引用先前的捕獲組。
import re
string1 = "html python"
string2 = "python python"
string3 = "java java"
pattern = r"(.+) 1"
match1 = re.match(pattern,string1)
match2 = re.match(pattern,string2)
match3 = re.match(pattern,string3)
if match1:
print(match1.group())
print("match 1")
if match2:
print(match2.group())
print("match 2")
if match3:
print(match3.group())
print("match 3")
執行結果:
>>>
python python
match 2
java java
match 3
>>>
注意:(.+) 1 不等同於 (.+)(.+),因為 1 引用第一組的表示式,即匹配表示式本身,而不是正則匹配模式。
正則中還有一些特殊的匹配模式 d, s, 和 w, 它們匹配數字,空白和單詞字元。在 ASCII 模式里正則裡等同 [0-9], [
v] 和 [a-zA-Z0-9], 但是在 Unicode 模式裡 w 匹配一個字。
如果我們把這幾個字母變成大寫 D, S, 和 W, 那麼意味著匹配模式相反。比如: D 匹配非數字。
import re
string1 = "python 2017!"
string2 = "1,00,867!"
string3 = "!@#?"
pattern = r"(D+d)"
match1 = re.match(pattern,string1)
match2 = re.match(pattern,string2)
match3 = re.match(pattern,string3)
if match1:
print(match1.group())
print("match 1")
if match2:
print(match2.group())
print("match 2")
if match3:
print(match3.group())
print("match 3")
執行結果:
>>>
python 2
match 1
>>>
(D+d) 意味著匹配一個或者多個非數字後面跟隨一個數字。
特殊匹配
還有一些特殊的匹配表示式 A, , 和 。A 僅匹配字串的開始,在大多數條件下,它的作用等同於在模式中使用 ^。 僅匹配字串的結束,在大多數情況下,相等於 $。
匹配一個詞的邊界。一個詞的邊界就是一個詞不被另外一個詞跟隨的位置或者不是另一個詞彙字元前邊的位置。相當於w 和 W 之間有個一個空字串。
B 匹配一個非單詞邊界。它匹配一個前後字元都是相同型別的位置:都是單詞或者都不是單詞。一個字符串的開始和結尾都被認為是非單詞。
import re
string1 = "The dog eat!"
string2 = "<dog>dog<>?"
string3 = "dogeatpython"
pattern = r"(dog)"
search1 = re.search(pattern,string1)
search2 = re.search(pattern,string2)
search3 = re.search(pattern,string3)
if search1:
print(search1.group())
print("search 1")
if search2:
print(search2.group())
print("search 2")
if search3:
print(search3.group())
print("search 3")
執行結果:
>>>
dog
search 1
dog
search 2
>>>
注意:一個匹配詞的邊界並不包含在匹配的內容中,換句話說,一個匹配的詞的邊界的內容的長度是0。(dog) 匹配的結果是 “dog“。
“美滿婚姻並非 “壁人成雙”,而是不完美的一雙學會互相欣賞彼此的差別。” – 大衛·鮑伊