re-正則表達式

  1. 簡介

這個模塊提供了與 Perl 語言類似的正則表達式匹配操作。

模式和被搜索的字符串既可以是 Unicode 字符串 (str) ,也可以是8位字節(jié)串 (bytes)。 但是,Unicode 字符串與8位字節(jié)串不能混用:也就是說,你不能用一個字節(jié)串模式去匹配 Unicode 字符串,反之亦然;類似地,當(dāng)進行替換操作時,替換字符串的類型也必須與所用的模式和搜索字符串的類型一致。

正則表達式使用反斜杠字符 ('') 來表示特殊形式或是允許在使用特殊字符時不引發(fā)它們的特殊含義。 這會與 Python 的字符串字面值中對相同字符出于相同目的的用法產(chǎn)生沖突;例如,要匹配一個反斜杠字面值,用戶可能必須寫成 '\\' 來作為模式字符串,因為正則表達式必須為 \,而每個反斜杠在普通 Python 字符串字面值中又必須表示為 \。 而且還要注意,在 Python 的字符串字面值中使用的反斜杠如果有任何無效的轉(zhuǎn)義序列,現(xiàn)在將會產(chǎn)生 DeprecationWarning 并將在未來改為 SyntaxError。 此行為即使對于正則表達式來說有效的轉(zhuǎn)義字符同樣會發(fā)生。

解決辦法是對于正則表達式樣式使用 Python 的原始字符串表示法;在帶有 'r' 前綴的字符串字面值中,反斜杠不必做任何特殊處理。 因此 r"\n" 表示包含 '' 和 'n' 兩個字符的字符串,而 "\n" 則表示只包含一個換行符的字符串。 樣式在 Python 代碼中通常都會使用這種原始字符串表示法來表示。

絕大部分正則表達式操作都提供為模塊函數(shù)和方法,在 編譯正則表達式. 這些函數(shù)是一個捷徑,不需要先編譯一個正則對象,但是損失了一些優(yōu)化參數(shù)。

參見 第三方模塊 regex , 提供了與標(biāo)準庫 re 模塊兼容的API接口, 同時還提供了額外的功能和更全面的Unicode支持。

  1. 模塊內(nèi)容

模塊定義了幾個函數(shù),常量,和一個例外。有些函數(shù)是編譯后的正則表達式方法的簡化版本(少了一些特性)。絕大部分重要的應(yīng)用,總是會先將正則表達式編譯,之后在進行操作。

re.compile(pattern, flags=0)
將正則表達式的樣式編譯為一個 正則表達式對象 (正則對象),可以用于匹配,通過這個對象的方法 match(), search() 以及其他如下描述。

這個表達式的行為可以通過指定 標(biāo)記 的值來改變。值可以是以下任意變量,可以通過位的OR操作來結(jié)合( | 操作符)。

序列
prog = re.compile(pattern)
result = prog.match(string)

等價于
result = re.match(pattern, string)

如果需要多次使用這個正則表達式的話,使用 re.compile() 和保存這個正則對象以便復(fù)用,可以讓程序更加高效。

注解
通過 re.compile() 編譯后的樣式,和模塊級的函數(shù)會被緩存, 所以少數(shù)的正則表達式使用無需考慮編譯的問題。

re.A
re.ASCII
讓 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,而不是Unicode。這只對Unicode樣式有效,會被byte樣式忽略。相當(dāng)于前面語法中的內(nèi)聯(lián)標(biāo)志 (?a) 。

注意,為了保持向后兼容, re.U 標(biāo)記依然存在(還有他的同義 re.UNICODE 和嵌入形式 (?u) ) , 但是這些在 Python 3 是冗余的,因為默認字符串已經(jīng)是Unicode了(并且Unicode匹配不允許byte出現(xiàn))。

re.DEBUG
顯示編譯時的debug信息,沒有內(nèi)聯(lián)標(biāo)記。

re.I
re.IGNORECASE
進行忽略大小寫匹配;表達式如 [A-Z] 也會匹配小寫字符。Unicode匹配(比如 ü 匹配 ü)同樣有用,除非設(shè)置了 re.ASCII 標(biāo)記來禁用非ASCII匹配。當(dāng)前語言區(qū)域不會改變這個標(biāo)記,除非設(shè)置了 re.LOCALE 標(biāo)記。這個相當(dāng)于內(nèi)聯(lián)標(biāo)記 (?i) 。

注意,當(dāng)設(shè)置了 IGNORECASE 標(biāo)記,搜索Unicode樣式 [a-z] 或 [A-Z] 的結(jié)合時,它將會匹配52個ASCII字符和4個額外的非ASCII字符: '?' (U+0130, 拉丁大寫的 I 帶個點在上面), '?' (U+0131, 拉丁小寫沒有點的 I ), '?' (U+017F, 拉丁小寫長 s) and 'K' (U+212A, 開爾文符號).如果使用 ASCII 標(biāo)記,就只匹配 'a' 到 'z' 和 'A' 到 'Z' 。

re.L
re.LOCALE
由當(dāng)前語言區(qū)域決定 \w, \W, \b, \B 和大小寫敏感匹配。這個標(biāo)記只能對byte樣式有效。這個標(biāo)記不推薦使用,因為語言區(qū)域機制很不可靠,它一次只能處理一個 "習(xí)慣”,而且只對8位字節(jié)有效。Unicode匹配在Python 3 里默認啟用,并可以處理不同語言。 這個對應(yīng)內(nèi)聯(lián)標(biāo)記 (?L) 。

在 3.6 版更改: re.LOCALE 只能用于byte樣式,而且不能和 re.ASCII 一起用。

在 3.7 版更改: 設(shè)置了 re.LOCALE 標(biāo)記的編譯正則對象不再在編譯時依賴語言區(qū)域設(shè)置。語言區(qū)域設(shè)置只在匹配的時候影響其結(jié)果。

re.M
re.MULTILINE
設(shè)置以后,樣式字符 '^' 匹配字符串的開始,和每一行的開始(換行符后面緊跟的符號);樣式字符 '' 匹配字符串尾,和每一行的結(jié)尾(換行符前面那個符號)。默認情況下,’^’ 匹配字符串頭,'' 匹配字符串尾。對應(yīng)內(nèi)聯(lián)標(biāo)記 (?m) 。

re.S
re.DOTALL
讓 '.' 特殊字符匹配任何字符,包括換行符;如果沒有這個標(biāo)記,'.' 就匹配 除了 換行符的其他任意字符。對應(yīng)內(nèi)聯(lián)標(biāo)記 (?s) 。

re.X
re.VERBOSE
這個標(biāo)記允許你編寫更具可讀性更友好的正則表達式。通過分段和添加注釋??瞻追枙缓雎裕窃谝粋€字符集合當(dāng)中或者由反斜杠轉(zhuǎn)義,或者在 *?, (?: or (?P<…> 分組之內(nèi)。當(dāng)一個行內(nèi)有 # 不在字符集和轉(zhuǎn)義序列,那么它之后的所有字符都是注釋。

意思就是下面兩個正則表達式等價地匹配一個十進制數(shù)字:

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

對應(yīng)內(nèi)聯(lián)標(biāo)記 (?x) 。

re.search(pattern, string, flags=0)
掃描整個 字符串 找到匹配樣式的第一個位置,并返回一個相應(yīng)的 匹配對象。如果沒有匹配,就返回一個 None ; 注意這和找到一個零長度匹配是不同的。

re.match(pattern, string, flags=0)
如果 string 開始的0或者多個字符匹配到了正則表達式樣式,就返回一個相應(yīng)的 匹配對象 。 如果沒有匹配,就返回 None ;注意它跟零長度匹配是不同的。

注意即便是 MULTILINE 多行模式, re.match() 也只匹配字符串的開始位置,而不匹配每行開始。

如果你想定位 string 的任何位置,使用 search() 來替代(也可參考 search() vs. match() )

re.fullmatch(pattern, string, flags=0)
如果整個 string 匹配到正則表達式樣式,就返回一個相應(yīng)的 匹配對象 。 否則就返回一個 None ;注意這跟零長度匹配是不同的。

re.split(pattern, string, maxsplit=0, flags=0)
用 pattern 分開 string 。 如果在 pattern 中捕獲到括號,那么所有的組里的文字也會包含在列表里。如果 maxsplit 非零, 最多進行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一個元素。

re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']

如果分隔符里有捕獲組合,并且匹配到字符串的開始,那么結(jié)果將會以一個空字符串開始。對于結(jié)尾也是一樣

re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']

這樣的話,分隔組將會出現(xiàn)在結(jié)果列表中同樣的位置。
樣式的空匹配將分開字符串,但只在不相臨的狀況生效。

re.split(r'\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
re.split(r'\W', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
re.split(r'(\W
)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']

re.findall(pattern, string, flags=0)
對 string 返回一個不重復(fù)的 pattern 的匹配列表, string 從左到右進行掃描,匹配按找到的順序返回。如果樣式里存在一到多個組,就返回一個組合列表;就是一個元組的列表(如果樣式里有超過一個組合的話)??掌ヅ湟矔诮Y(jié)果里。

re.finditer(pattern, string, flags=0)
pattern 在 string 里所有的非重復(fù)匹配,返回為一個迭代器 iterator 保存了 匹配對象 。 string 從左到右掃描,匹配按順序排列??掌ヅ湟舶诮Y(jié)果里。

re.sub(pattern, repl, string, count=0, flags=0)
返回通過使用 repl 替換在 string 最左邊非重疊出現(xiàn)的 pattern 而獲得的字符串。 如果樣式?jīng)]有找到,則不加改變地返回 string。 repl 可以是字符串或函數(shù);如為字符串,則其中任何反斜杠轉(zhuǎn)義序列都會被處理。 也就是說,\n 會被轉(zhuǎn)換為一個換行符,\r 會被轉(zhuǎn)換為一個回車附,依此類推。 未知的 ASCII 字符轉(zhuǎn)義序列保留在未來使用,會被當(dāng)作錯誤來處理。 其他未知轉(zhuǎn)義序列例如 & 會保持原樣。 向后引用像是 \6 會用樣式中第 6 組所匹配到的子字符串來替換。 例如:

re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9])\s(\s):',
... r'static PyObject
\npy_\1(void)\n{',
... 'def myfunc():')
'static PyObject*\npy_myfunc(void)\n{'

如果 repl 是一個函數(shù),那它會對每個非重復(fù)的 pattern 的情況調(diào)用。這個函數(shù)只能有一個 匹配對象 參數(shù),并返回一個替換后的字符串。比如

def dashrepl(matchobj):
... if matchobj.group(0) == '-': return ' '
... else: return '-'
re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
'Baked Beans & Spam'

樣式可以是一個字符串或者一個 樣式對象 。

可選參數(shù) count 是要替換的最大次數(shù);count 必須是非負整數(shù)。如果忽略這個參數(shù),或者設(shè)置為0,所有的匹配都會被替換??掌ヅ渲辉诓幌嗯R連續(xù)的情況被更替,所以 sub('x*', '-', 'abxd') 返回 '-a-b--d-' 。

在字符串類型的 repl 參數(shù)里,如上所述的轉(zhuǎn)義和向后引用中,\g<name> 會使用命名組合 name,(在 (?P<name>…) 語法中定義) \g<number> 會使用數(shù)字組;\g<2> 就是 \2,但它避免了二義性,如 \g<2>0。 \20 就會被解釋為組20,而不是組2后面跟隨一個字符 '0'。向后引用 \g<0> 把 pattern 作為一整個組進行引用。

在 3.1 版更改: 增加了可選標(biāo)記參數(shù)。

在 3.5 版更改: 不匹配的組合替換為空字符串。

在 3.6 版更改: pattern 中的未知轉(zhuǎn)義(由 '' 和一個 ASCII 字符組成)被視為錯誤。

在 3.7 版更改: repl 中的未知轉(zhuǎn)義(由 '' 和一個 ASCII 字符組成)被視為錯誤。

在 3.7 版更改: 樣式中的空匹配相鄰接時會被替換。

re.subn(pattern, repl, string, count=0, flags=0)
行為與 sub() 相同,但是返回一個元組 (字符串, 替換次數(shù)).

在 3.1 版更改: 增加了可選標(biāo)記參數(shù)。

在 3.5 版更改: 不匹配的組合替換為空字符串。

re.escape(pattern)
轉(zhuǎn)義 pattern 中的特殊字符。如果你想對任意可能包含正則表達式元字符的文本字符串進行匹配,它就是有用的。比如

print(re.escape('http://www.python.org'))
http://www.python.org

legal_chars = string.ascii_lowercase + string.digits + "!#%&'*+-.^_`|~:" print('[%s]+' % re.escape(legal_chars)) [abcdefghijklmnopqrstuvwxyz0123456789!\#\%&'*+-.^_`|~:]+

operators = ['+', '-', '', '/', '*']
print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|-|+|**|*

這個函數(shù)不能被用于 sub() 和 subn() 的替換字符串,只有反斜杠應(yīng)該被轉(zhuǎn)義。 例如:

digits_re = r'\d+'
sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
print(re.sub(digits_re, digits_re.replace('\', r'\'), sample))
/usr/sbin/sendmail - \d+ errors, \d+ warnings

re.purge()
清除正則表達式緩存。

exception re.error(msg, pattern=None, pos=None)
raise 一個例外。當(dāng)傳遞到函數(shù)的字符串不是一個有效正則表達式的時候(比如,包含一個不匹配的括號)或者其他錯誤在編譯時或匹配時產(chǎn)生。如果字符串不包含樣式匹配,是不會被視為錯誤的。錯誤實例有以下附加屬性:

msg
未格式化的錯誤消息。

pattern
正則表達式樣式。

pos
編譯失敗的 pattern 的位置索引(可以是 None )。

lineno
對應(yīng) pos (可以是 None) 的行號。

colno
對應(yīng) pos (可以是 None) 的列號。

  1. 正則表達式對象(正則對象)
    編譯后的正則表達式對象支持以下方法和屬性:

Pattern.search(string[, pos[, endpos]])
掃描整個 string 尋找第一個匹配的位置, 并返回一個相應(yīng)的 匹配對象。如果沒有匹配,就返回 None ;注意它和零長度匹配是不同的。

可選的第二個參數(shù) pos 給出了字符串中開始搜索的位置索引;默認為 0,它不完全等價于字符串切片; '^' 樣式字符匹配字符串真正的開頭,和換行符后面的第一個字符,但不會匹配索引規(guī)定開始的位置。

可選參數(shù) endpos 限定了字符串搜索的結(jié)束;它假定字符串長度到 endpos , 所以只有從 pos 到 endpos - 1 的字符會被匹配。如果 endpos 小于 pos,就不會有匹配產(chǎn)生;另外,如果 rx 是一個編譯后的正則對象, rx.search(string, 0, 50) 等價于 rx.search(string[:50], 0)。

pattern = re.compile("d")
pattern.search("dog") # Match at index 0
<re.Match object; span=(0, 1), match='d'>
pattern.search("dog", 1) # No match; search doesn't include the "d"

Pattern.match(string[, pos[, endpos]])
如果 string 的 開始位置 能夠找到這個正則樣式的任意個匹配,就返回一個相應(yīng)的 匹配對象。如果不匹配,就返回 None ;注意它與零長度匹配是不同的。
可選參數(shù) pos 和 endpos 與 search() 含義相同。

pattern = re.compile("o")
pattern.match("dog") # No match as "o" is not at the start of "dog".
pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog".
<re.Match object; span=(1, 2), match='o'>

如果你想定位匹配在 string 中的位置,使用 search() 來替代(另參考 search() vs. match())。

Pattern.fullmatch(string[, pos[, endpos]])?
如果整個 string 匹配這個正則表達式,就返回一個相應(yīng)的 匹配對象 。 否則就返回 None ; 注意跟零長度匹配是不同的。

可選參數(shù) pos 和 endpos 與 search() 含義相同。

pattern = re.compile("o[gh]")
pattern.fullmatch("dog") # No match as "o" is not at the start of "dog".
pattern.fullmatch("ogre") # No match as not the full string matches.
pattern.fullmatch("doggie", 1, 3) # Matches within given limits.
<re.Match object; span=(1, 3), match='og'>

Pattern.split(string, maxsplit=0)?
等價于 split() 函數(shù),使用了編譯后的樣式。
Pattern.findall(string[, pos[, endpos]])
類似函數(shù) findall() , 使用了編譯后樣式,但也可以接收可選參數(shù) pos 和 endpos ,限制搜索范圍,就像 search()。

Pattern.finditer(string[, pos[, endpos]])
類似函數(shù) finiter() , 使用了編譯后樣式,但也可以接收可選參數(shù) pos 和 endpos ,限制搜索范圍,就像 search()。

Pattern.sub(repl, string, count=0)
等價于 sub() 函數(shù),使用了編譯后的樣式。

Pattern.subn(repl, string, count=0)
等價于 subn() 函數(shù),使用了編譯后的樣式。

Pattern.flags
正則匹配標(biāo)記。這是可以傳遞給 compile() 的參數(shù),任何 (?…) 內(nèi)聯(lián)標(biāo)記,隱性標(biāo)記比如 UNICODE 的結(jié)合。

Pattern.groups
捕獲組合的數(shù)量。

Pattern.groupindex
映射由 (?P<id>) 定義的命名符號組合和數(shù)字組合的字典。如果沒有符號組,那字典就是空的。

Pattern.pattern
編譯對象的原始樣式字符串。

在 3.7 版更改: 添加 copy.copy() 和 copy.deepcopy() 函數(shù)的支持。編譯后的正則表達式對象被認為是原子性的。

  1. 匹配對象
    匹配對象總是有一個布爾值 True。如果沒有匹配的話 match() 和 search() 返回 None 所以你可以簡單的用 if 語句來判斷是否匹配

match = re.search(pattern, string)
if match:
process(match)

匹配對象支持以下方法和屬性:
Match.expand(template)
對 template 進行反斜杠轉(zhuǎn)義替換并且返回,就像 sub() 方法中一樣。轉(zhuǎn)義如同 \n 被轉(zhuǎn)換成合適的字符,數(shù)字引用(\1, \2)和命名組合(\g<1>, \g<name>) 替換為相應(yīng)組合的內(nèi)容。

在 3.5 版更改: 不匹配的組合替換為空字符串。

Match.group([group1, ...])
返回一個或者多個匹配的子組。如果只有一個參數(shù),結(jié)果就是一個字符串,如果有多個參數(shù),結(jié)果就是一個元組(每個參數(shù)對應(yīng)一個項),如果沒有參數(shù),組1默認到0(整個匹配都被返回)。 如果一個組N 參數(shù)值為 0,相應(yīng)的返回值就是整個匹配字符串;如果它是一個范圍 [1..99],結(jié)果就是相應(yīng)的括號組字符串。如果一個組號是負數(shù),或者大于樣式中定義的組數(shù),一個 IndexError 索引錯誤就 raise。如果一個組包含在樣式的一部分,并被匹配多次,就返回最后一個匹配。:

m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
m.group(0) # The entire match
'Isaac Newton'
m.group(1) # The first parenthesized subgroup.
'Isaac'
m.group(2) # The second parenthesized subgroup.
'Newton'
m.group(1, 2) # Multiple arguments give us a tuple.
('Isaac', 'Newton')

如果正則表達式使用了 (?P<name>…) 語法, groupN 參數(shù)就也可能是命名組合的名字。如果一個字符串參數(shù)在樣式中未定義為組合名,一個 IndexError 就 raise。
一個相對復(fù)雜的例子

m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
m.group('first_name')
'Malcolm'
m.group('last_name')
'Reynolds'

命名組合同樣可以通過索引值引用

m.group(1)
'Malcolm'
m.group(2)
'Reynolds'

如果一個組匹配成功多次,就只返回最后一個匹配

m = re.match(r"(..)+", "a1b2c3") # Matches 3 times.
m.group(1) # Returns only the last match.
'c3

Match.getitem(g)
這個等價于 m.group(g)。這允許更方便的引用一個匹配

m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
m[0] # The entire match
'Isaac Newton'
m[1] # The first parenthesized subgroup.
'Isaac'
m[2] # The second parenthesized subgroup.
'Newton'

Match.groups(default=None)
返回一個元組,包含所有匹配的子組,在樣式中出現(xiàn)的從1到任意多的組合。 default 參數(shù)用于不參與匹配的情況,默認為 None。

例如

m = re.match(r"(\d+).(\d+)", "24.1632")
m.groups()
('24', '1632')

如果我們使小數(shù)點可選,那么不是所有的組都會參與到匹配當(dāng)中。這些組合默認會返回一個 None ,除非指定了 default 參數(shù)。

m = re.match(r"(\d+).?(\d+)?", "24")
m.groups() # Second group defaults to None.
('24', None)
m.groups('0') # Now, the second group defaults to '0'.
('24', '0')

Match.groupdict(default=None)
返回一個字典,包含了所有的 命名 子組。key就是組名。 default 參數(shù)用于不參與匹配的組合;默認為 None。 例如

m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}

Match.start([group])
Match.end([group])
返回 group 匹配到的字串的開始和結(jié)束標(biāo)號。group 默認為0(意思是整個匹配的子串)。如果 group 存在,但未產(chǎn)生匹配,就返回 -1 。對于一個匹配對象 m, 和一個未參與匹配的組 g ,組 g (等價于 m.group(g))產(chǎn)生的匹配是

m.string[m.start(g):m.end(g)]
注意 m.start(group) 將會等于 m.end(group) ,如果 group 匹配一個空字符串的話。比如,在 m = re.search('b(c?)', 'cba') 之后,m.start(0) 為 1, m.end(0) 為 2, m.start(1) 和 m.end(1) 都是 2, m.start(2) raise 一個 IndexError 例外。

這個例子會從email地址中移除掉 remove_this

email = "tony@tiremove_thisger.net"
m = re.search("remove_this", email)
email[:m.start()] + email[m.end():]
'tony@tiger.net'

Match.span([group])
對于一個匹配 m , 返回一個二元組 (m.start(group), m.end(group)) 。 注意如果 group 沒有在這個匹配中,就返回 (-1, -1) 。group 默認為0,就是整個匹配。

Match.pos
pos 的值,會傳遞給 search() 或 match() 的方法 a 正則對象 。這個是正則引擎開始在字符串搜索一個匹配的索引位置。

Match.endpos
endpos 的值,會傳遞給 search() 或 match() 的方法 a 正則對象 。這個是正則引擎停止在字符串搜索一個匹配的索引位置。

Match.lastindex
捕獲組的最后一個匹配的整數(shù)索引值,或者 None 如果沒有匹配產(chǎn)生的話。比如,對于字符串 'ab',表達式 (a)b, ((a)(b)), 和 ((ab)) 將得到 lastindex == 1 , 而 (a)(b) 會得到 lastindex == 2 。

Match.lastgroup
最后一個匹配的命名組名字,或者 None 如果沒有產(chǎn)生匹配的話。

Match.re
返回產(chǎn)生這個實例的 正則對象 , 這個實例是由 正則對象的 match() 或 search() 方法產(chǎn)生的。

Match.string
傳遞到 match() 或 search() 的字符串。

在 3.7 版更改: 添加了對 copy.copy() 和 copy.deepcopy() 的支持。匹配對象被看作是原子性的。

  1. 正則表達式例子
    ·檢查對子
    在這個例子里,我們使用以下輔助函數(shù)來更好地顯示匹配對象:
    def displaymatch(match):
    if match is None:
    return None
    return '<Match: %r, groups=%r>' % (match.group(), match.groups())

假設(shè)你在寫一個撲克程序,一個玩家的一手牌為五個字符的串,每個字符表示一張牌,"a" 就是 A, "k" K, "q" Q, "j" J, "t" 為 10, "2" 到 "9" 表示2 到 9。

要看給定的字符串是否有效,我們可以按照以下步驟

valid = re.compile(r"^[a2-9tjqk]{5}$")
displaymatch(valid.match("akt5q")) # Valid.
"<Match: 'akt5q', groups=()>"
displaymatch(valid.match("akt5e")) # Invalid.
displaymatch(valid.match("akt")) # Invalid.
displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"

最后一手牌,"727ak" ,包含了一個對子,或者兩張同樣數(shù)值的牌。要用正則表達式匹配它,應(yīng)該使用向后引用如下

pair = re.compile(r".(.).\1")
displaymatch(pair.match("717ak")) # Pair of 7s.
"<Match: '717', groups=('7',)>"
displaymatch(pair.match("718ak")) # No pairs.
displaymatch(pair.match("354aa")) # Pair of aces.
"<Match: '354aa', groups=('a',)>"

要找出對子由什么牌組成,開發(fā)者可以按照下面的方式來使用匹配對象的 group() 方法:

pair = re.compile(r".(.).\1")
pair.match("717ak").group(1)
'7'

Error because re.match() returns None, which doesn't have a group() method:

pair.match("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
re.match(r".(.).\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'

pair.match("354aa").group(1)
'a'

  1. search() VS match()
    Python 提供了兩種不同的操作:基于 re.match() 檢查字符串開頭,或者 re.search() 檢查字符串的任意位置(默認Perl中的行為)。

例如

re.match("c", "abcdef") # No match
re.search("c", "abcdef") # Match
<re.Match object; span=(2, 3), match='c'>

在 search() 中,可以用 '^' 作為開始來限制匹配到字符串的首位

re.match("c", "abcdef") # No match
re.search("^c", "abcdef") # No match
re.search("^a", "abcdef") # Match
<re.Match object; span=(0, 1), match='a'>

注意 MULTILINE 多行模式中函數(shù) match() 只匹配字符串的開始,但使用 search() 和以 '^' 開始的正則表達式會匹配每行的開始

re.match('X', 'A\nB\nX', re.MULTILINE) # No match
re.search('^X', 'A\nB\nX', re.MULTILINE) # Match
<re.Match object; span=(4, 5), match='X'>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容