在上一篇文章中,我們介紹了 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], [ \t\n\r\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, \Z, 和 \b。\A 僅匹配字符串的開始,在大多數條件下,它的作用等同於在模式中使用 ^。 \Z 僅匹配字符串的結束,在大多數情況下,相等於 $。
\b 匹配一個詞的邊界。一個詞的邊界就是一個詞不被另外一個詞跟隨的位置或者不是另一個詞匯字符前邊的位置。相當於\w 和 \W 之間有個一個空字符串。
\B 匹配一個非單詞邊界。它匹配一個前后字符都是相同類型的位置:都是單詞或者都不是單詞。一個字符串的開始和結尾都被認為是非單詞。
import re string1 = "The dog eat!" string2 = "<dog>dog<>?" string3 = "dogeatpython" pattern = r"\b(dog)\b" 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。\b(dog)\b 匹配的結果是 "dog"。
“美滿婚姻並非 “壁人成雙”,而是不完美的一雙學會互相欣賞彼此的差別。” -- 大衛·鮑伊
