方法歸納
| 方法 | 描述 |
|---|---|
| findall | 將字符串中所有的非重疊匹配模式以列表形式返回 |
| finditer | 與findall類似,但返回的是迭代器 |
| match | 在字符串起始位置匹配模式,也可以將模式組件匹配到分組中; 如果模式匹配上了,返回一個(gè)匹配對(duì)象,否則返回None |
| search | 掃描字符串的匹配模式,如果掃面到了返回匹配對(duì)象; 與match方法不同的是,search方法的匹配可以是字符串的任意位置, 而不僅僅是字符串的起始位置 |
| split | 根據(jù)模式,將字符串拆分為多個(gè)部分 |
| sub,subn | 用替換表達(dá)式替換字符串中所有的匹配(sub)或第n個(gè)出現(xiàn)的匹配串(subn); 使用符號(hào)\1,\2....來引用替換字符串中匹配組的元素 |
compile
正則表達(dá)式提供了一種在文本中靈活查找或匹配字符串模式的方法。單個(gè)表達(dá)式通常被稱為regex,是根據(jù)正則表達(dá)式語(yǔ)言形成的字符串。Python內(nèi)建的re模塊是用于將正則表達(dá)式應(yīng)用到字符串上的庫(kù)。接下來展示一些re模塊的實(shí)例。
re模塊主要有三個(gè)主題:模式匹配、替代、拆分。當(dāng)然,這三個(gè)主題是相關(guān)聯(lián)的。一個(gè)正則表達(dá)式描述了在文本中需要定位的一種模式,可以用于多種目標(biāo)。
讓我們來看一個(gè)簡(jiǎn)單的示例:假設(shè)我們想將含有多種空白字符(制表符、空格、換行符)的字符串拆分開。描述一個(gè)或多個(gè)空白字符的正則表達(dá)式是\s+:
import re
text = "foo bar\t baz \tqux"
re.split('\s+', text)
當(dāng)調(diào)用re.split('\s+', text)時(shí),正則表達(dá)式首先會(huì)被編譯,然后正則表達(dá)式的split方法在傳入文本上被調(diào)用。也可以使用re.compile自行編譯,形成一個(gè)可復(fù)用的正則表達(dá)式對(duì)象。
regex = re.compile('\s+')
regex.split(text)
以上兩段執(zhí)行結(jié)果相同:
['foo', 'bar', 'baz', 'qux']
findall
如果需要獲得的是一個(gè)所有匹配正則表達(dá)式的模式的列表,你可以使用findall方法:
regex.findall(text)
//out: [' ', '\t ', ' \t']
PS:為了在正則表達(dá)式中避免轉(zhuǎn)義符\的影響,可以使用原生字符串語(yǔ)法,比如 r'C:\x' 或者用等價(jià)的 'C:\x'
如果需要將相同的表達(dá)式應(yīng)用在多個(gè)字符串上,推薦使用re.compile創(chuàng)建一個(gè)正則表達(dá)式對(duì)象,這樣做有利于節(jié)約CPU周期。
search、match
match和search與findall相關(guān)性很大。findall返回的是字符串中所有的匹配項(xiàng),而search返回的僅僅是第一個(gè)匹配項(xiàng)。match更為嚴(yán)格,它只在字符串的起始位置進(jìn)行匹配。我們來看下一個(gè)示例,一段文本和一個(gè)可以識(shí)別大部分電子郵件地址的正則表達(dá)式:
在文本上使用findall會(huì)生成一個(gè)電子郵件地址的列表:
text = '''Dava dava@google.com
Steve steve@gmail.com
Rob rob@gmail.com
Ryan ryan@yahoo.com
'''
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
# re.IGNORECASE 使正則表達(dá)式不區(qū)分大小寫
regex = re.compile(pattern, flags=re.IGNORECASE)
regex.findall(text)
//out: ['dava@google.com', 'steve@gmail.com', 'rob@gmail.com', 'ryan@yahoo.com']
search返回的是文本中第一個(gè)匹配到的電子郵件地址。對(duì)于前面提到的正則表達(dá)式,匹配對(duì)象只能告訴我們模式在字符串中起始和結(jié)束的位置:
m = regex.search(text)
m
//out: <re.Match object; span=(5, 20), match='dava@google.com'>
text[m.start():m.end()]
//out: 'dava@google.com'
regex.match只在模式出現(xiàn)于字符串起始位置時(shí)進(jìn)行匹配,如果沒有匹配到,返回None:
print(regex.match(text))
//out: None
sub
sub會(huì)返回一個(gè)新的字符串,原字符串中的模式會(huì)被一個(gè)新的字符串替代:
s = regex.sub('REDACTED',text)
print(s)
//out: Dava REDACTED
Steve REDACTED
Rob REDACTED
Ryan REDACTED
擴(kuò)展
假設(shè)想查找電子郵件地址,并將每個(gè)地址分為三個(gè)部分:用戶名、域名和域名后綴。要實(shí)現(xiàn)這一點(diǎn),可以用括號(hào)將模式包起來。由下面修改后的正則表達(dá)式產(chǎn)生的匹配對(duì)象的groups方法,返回的是模式組件的元組:
pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
regex = re.compile(pattern, flags = re.IGNORECASE)
m = regex.match('wesm@bright.net')
m.groups()
//out: ('wesm', 'bright', 'net')
當(dāng)模式可以分組時(shí),findall返回的是包含元組的列表:
regex.findall(text)
//out: [('dava', 'google', 'com'),
('steve', 'gmail', 'com'),
('rob', 'gmail', 'com'),
('ryan', 'yahoo', 'com')]
sub也可以使用特殊符號(hào),如\1和\2,訪問每個(gè)匹配對(duì)象中的分組。符號(hào)\1代表的是第一個(gè)匹配分組,\2代表的是第二個(gè)匹配分組,以此類推:
L = regex.sub(r'Username: \1, Domain: \2, Suffix: \3', text)
print(L)
//out: Dava Username: dava, Domain: google, Suffix: com
Steve Username: steve, Domain: gmail, Suffix: com
Rob Username: rob, Domain: gmail, Suffix: com
Ryan Username: ryan, Domain: yahoo, Suffix: com
去掉\3,便于理解
L = regex.sub(r'Username: \1, Domain: \2, Suffix: ', text)
print(L)
//out:Dava Username: dava, Domain: google, Suffix:
Steve Username: steve, Domain: gmail, Suffix:
Rob Username: rob, Domain: gmail, Suffix:
Ryan Username: ryan, Domain: yahoo, Suffix: