? ? ? ? 模式和被搜索的字符串既可以是 Unicode 字符串 (str) ,也可以是8位字節(jié)串 (bytes)绝淡。 但是宙刘,Unicode 字符串與8位字節(jié)串不能混用:也就是說(shuō),你不能用一個(gè)字節(jié)串模式去匹配 Unicode 字符串牢酵,反之亦然悬包;類(lèi)似地,當(dāng)進(jìn)行替換操作時(shí)馍乙,替換字符串的類(lèi)型也必須與所用的模式和搜索字符串的類(lèi)型一致布近。
?? ??? ?正則表達(dá)式使用反斜杠('\')來(lái)表示特殊形式,或者把特殊字符轉(zhuǎn)義成普通字符丝格。 而反斜杠在普通的 Python 字符串里也有相同的作用吊输,所以就產(chǎn)生了沖突。比如說(shuō)铁追,要匹配一個(gè)字面上的反斜杠季蚂,正則表達(dá)式模式不得不寫(xiě)成?'\\\\',因?yàn)檎齽t表達(dá)式里匹配一個(gè)反斜杠必須是?\\?琅束,而每個(gè)反斜杠在普通的 Python 字符串里都要寫(xiě)成?\\?扭屁。
?? ??? ?解決辦法是對(duì)于正則表達(dá)式樣式使用 Python 的原始字符串表示法;在帶有?'r'?前綴的字符串字面值中涩禀,反斜杠不必做任何特殊處理料滥。 因此?r"\n"?表示包含?'\'?和?'n'?兩個(gè)字符的字符串,而?"\n"?則表示只包含一個(gè)換行符的字符串艾船。 樣式在 Python 代碼中通常都會(huì)使用這種原始字符串表示法來(lái)表示葵腹。
絕大部分正則表達(dá)式操作都提供為模塊函數(shù)和方法,在?編譯正則表達(dá)式. 這些函數(shù)是一個(gè)捷徑屿岂,不需要先編譯一個(gè)正則對(duì)象践宴,但是損失了一些優(yōu)化參數(shù)。
參見(jiàn)
第三方模塊?regex?, 提供了與標(biāo)準(zhǔn)庫(kù)?re?模塊兼容的API接口, 同時(shí)還提供了額外的功能和更全面的Unicode支持爷怀。
正則表達(dá)式語(yǔ)法
一個(gè)正則表達(dá)式(或RE)指定了一集與之匹配的字符串阻肩;模塊內(nèi)的函數(shù)可以讓你檢查某個(gè)字符串是否跟給定的正則表達(dá)式匹配(或者一個(gè)正則表達(dá)式是否匹配到一個(gè)字符串,這兩種說(shuō)法含義相同)运授。
正則表達(dá)式可以拼接烤惊; 如果?A?和?B?都是正則表達(dá)式乔煞, 那么?AB?也是正則表達(dá)式。 通常柒室, 如果字符串?p?匹配?A?并且另一個(gè)字符串?q?匹配?B, 那么?pq?可以匹配 AB渡贾。除非?A?或者?B?包含低優(yōu)先級(jí)操作,A?和?B?存在邊界條件雄右;或者命名組引用空骚。所以,復(fù)雜表達(dá)式可以很容易的從這里描述的簡(jiǎn)單源語(yǔ)表達(dá)式構(gòu)建不脯。 了解更多正則表達(dá)式理論和實(shí)現(xiàn)府怯,參考the Friedl book?[Frie09]?刻诊,或者其他編譯器構(gòu)建的書(shū)籍防楷。
以下是正則表達(dá)式格式的簡(jiǎn)要說(shuō)明。更詳細(xì)的信息和演示则涯,參考?正則表達(dá)式HOWTO复局。
正則表達(dá)式可以包含普通或者特殊字符。絕大部分普通字符粟判,比如?'A',?'a', 或者?'0'亿昏,都是最簡(jiǎn)單的正則表達(dá)式。它們就匹配自身档礁。你可以拼接普通字符角钩,所以?last?匹配字符串?'last'. (在這一節(jié)的其他部分,我們將用?this?special?style?這種方式表示正則表達(dá)式呻澜,通常不帶引號(hào)递礼,要匹配的字符串用?'in?single?quotes'?,單引號(hào)形式羹幸。)
有些字符脊髓,比如?'|'?或者?'(',屬于特殊字符栅受。 特殊字符既可以表示它的普通含義将硝, 也可以影響它旁邊的正則表達(dá)式的解釋。
重復(fù)修飾符 (*,?+,??,?{m,n}, 等) 不能直接嵌套屏镊。這樣避免了非貪婪后綴???修飾符依疼,和其他實(shí)現(xiàn)中的修飾符產(chǎn)生的多義性。要應(yīng)用一個(gè)內(nèi)層重復(fù)嵌套而芥,可以使用括號(hào)涛贯。 比如,表達(dá)式?(?:a{6})*?匹配6個(gè)?'a'?字符重復(fù)任意次數(shù)蔚出。
特殊字符是:
.
(點(diǎn)) 在默認(rèn)模式弟翘,匹配除了換行的任意字符虫腋。如果指定了標(biāo)簽?DOTALL?,它將匹配包括換行符的任意字符稀余。
^
(插入符號(hào)) 匹配字符串的開(kāi)頭悦冀, 并且在?MULTILINE?模式也匹配換行后的首個(gè)符號(hào)。
$
匹配字符串尾或者換行符的前一個(gè)字符睛琳,在?MULTILINE?模式匹配換行符的前一個(gè)字符盒蟆。?foo?匹配?'foo'?和?'foobar'?, 但正則?foo$?只匹配?'foo'。更有趣的是师骗, 在?'foo1\nfoo2\n'?搜索?foo.$?历等,通常匹配?'foo2'?,但在?MULTILINE?模式 辟癌,可以匹配到?'foo1'?寒屯;在?'foo\n'?搜索?$?會(huì)找到兩個(gè)空串:一個(gè)在換行前,一個(gè)在字符串最后黍少。
*
對(duì)它前面的正則式匹配0到任意次重復(fù)寡夹, 盡量多的匹配字符串。?ab*?會(huì)匹配?'a'厂置,?'ab'菩掏, 或者?'a'``后面跟隨任意個(gè)?``'b'。
+
對(duì)它前面的正則式匹配1到任意次重復(fù)昵济。?ab+?會(huì)匹配?'a'?后面跟隨1個(gè)以上到任意個(gè)?'b'智绸,它不會(huì)匹配?'a'。
?
對(duì)它前面的正則式匹配0到1次重復(fù)访忿。?ab??會(huì)匹配?'a'?或者?'ab'瞧栗。
*?,?+?,???
'*',?'+',和?'?'?修飾符都是?貪婪的醉顽;它們?cè)谧址M(jìn)行盡可能多的匹配沼溜。有時(shí)候并不需要這種行為。如果正則式?<.*>?希望找到?'<a>?b?<c>'游添,它將會(huì)匹配整個(gè)字符串系草,而不僅是?'<a>'。在修飾符之后添加???將使樣式以?非貪婪`方式或者 :dfn:`最小?方式進(jìn)行匹配唆涝; 盡量?少?的字符將會(huì)被匹配找都。 使用正則式?<.*?>?將會(huì)僅僅匹配?'<a>'。
“{m}”
對(duì)其之前的正則式指定匹配?m?個(gè)重復(fù)廊酣;少于?m?的話就會(huì)導(dǎo)致匹配失敗能耻。比如,?a{6}?將匹配6個(gè)?'a'?, 但是不能是5個(gè)。
“{m, n}”
對(duì)正則式進(jìn)行?m?到?n?次匹配晓猛,在?m?和?n?之間取盡量多饿幅。 比如,a{3,5}?將匹配 3 到 5個(gè)?'a'戒职。忽略?m?意為指定下界為0栗恩,忽略?n?指定上界為無(wú)限次。 比如?a{4,}b?將匹配?'aaaab'?或者1000個(gè)?'a'?尾隨一個(gè)?'b'洪燥,但不能匹配?'aaab'磕秤。逗號(hào)不能省略,否則無(wú)法辨別修飾符應(yīng)該忽略哪個(gè)邊界捧韵。
{m,n}?
前一個(gè)修飾符的非貪婪模式市咆,只匹配盡量少的字符次數(shù)。比如再来,對(duì)于?'aaaaaa'蒙兰,?a{3,5}?匹配 5個(gè)?'a'?,而?a{3,5}??只匹配3個(gè)?'a'其弊。
\
轉(zhuǎn)義特殊字符(允許你匹配?'*',?'?', 或者此類(lèi)其他)癞己,或者表示一個(gè)特殊序列膀斋;特殊序列之后進(jìn)行討論梭伐。
如果你沒(méi)有使用原始字符串(?r'raw'?)來(lái)表達(dá)樣式,要牢記Python也使用反斜杠作為轉(zhuǎn)義序列仰担;如果轉(zhuǎn)義序列不被Python的分析器識(shí)別糊识,反斜杠和字符才能出現(xiàn)在字符串中。如果Python可以識(shí)別這個(gè)序列摔蓝,那么反斜杠就應(yīng)該重復(fù)兩次赂苗。這將導(dǎo)致理解障礙,所以高度推薦贮尉,就算是最簡(jiǎn)單的表達(dá)式拌滋,也要使用原始字符串。
[]
用于表示一個(gè)字符集合猜谚。在一個(gè)集合中:
字符可以單獨(dú)列出败砂,比如?[amk]?匹配?'a',?'m'魏铅, 或者?'k'昌犹。
可以表示字符范圍,通過(guò)用?'-'?將兩個(gè)字符連起來(lái)览芳。比如?[a-z]?將匹配任何小寫(xiě)ASCII字符斜姥,?[0-5][0-9]?將匹配從?00?到?59?的兩位數(shù)字,?[0-9A-Fa-f]?將匹配任何十六進(jìn)制數(shù)位。 如果?-?進(jìn)行了轉(zhuǎn)義 (比如?[a\-z])或者它的位置在首位或者末尾(如?[-a]?或?[a-])铸敏,它就只表示普通字符?'-'缚忧。
特殊字符在集合中,失去它的特殊含義杈笔。比如?[(+*)]?只會(huì)匹配這幾個(gè)文法字符?'(',?'+',?'*', or?')'搔谴。
字符類(lèi)如?\w?或者?\S?(如下定義) 在集合內(nèi)可以接受,它們可以匹配的字符由?ASCII?或者?LOCALE?模式?jīng)Q定桩撮。
不在集合范圍內(nèi)的字符可以通過(guò)?取反?來(lái)進(jìn)行匹配敦第。如果集合首字符是?'^'?,所有?不?在集合內(nèi)的字符將會(huì)被匹配店量,比如?[^5]?將匹配所有字符芜果,除了?'5',?[^^]?將匹配所有字符融师,除了?'^'.?^?如果不在集合首位右钾,就沒(méi)有特殊含義。
在集合內(nèi)要匹配一個(gè)字符?']'旱爆,有兩種方法舀射,要么就在它之前加上反斜杠,要么就把它放到集合首位怀伦。比如脆烟,?[()[\]{}]?和?[]()[{}]?都可以匹配括號(hào)。
|
A|B房待,?A?和?B?可以是任意正則表達(dá)式邢羔,創(chuàng)建一個(gè)正則表達(dá)式,匹配?A?或者?B. 任意個(gè)正則表達(dá)式可以用?'|'?連接桑孩。它也可以在組合(見(jiàn)下列)內(nèi)使用拜鹤。掃描目標(biāo)字符串時(shí),?'|'?分隔開(kāi)的正則樣式從左到右進(jìn)行匹配流椒。當(dāng)一個(gè)樣式完全匹配時(shí)敏簿,這個(gè)分支就被接受。意思就是宣虾,一旦?A?匹配成功惯裕,?B?就不再進(jìn)行匹配,即便它能產(chǎn)生一個(gè)更好的匹配安岂∏岵或者說(shuō),'|'?操作符絕不貪婪域那。 如果要匹配?'|'?字符咙边,使用?\|猜煮, 或者把它包含在字符集里,比如?[|].
(...)
(組合)败许,匹配括號(hào)內(nèi)的任意正則表達(dá)式王带,并標(biāo)識(shí)出組合的開(kāi)始和結(jié)尾。匹配完成后市殷,組合的內(nèi)容可以被獲取愕撰,并可以在之后用?\number?轉(zhuǎn)義序列進(jìn)行再次匹配,之后進(jìn)行詳細(xì)說(shuō)明醋寝。要匹配字符?'('?或者?')', 用?\(?或?\), 或者把它們包含在字符集合里:?[(],?[)].
(?…)
這是個(gè)擴(kuò)展標(biāo)記法 (一個(gè)?'?'?跟隨?'('?并無(wú)含義)搞挣。?'?'?后面的第一個(gè)字符決定了這個(gè)構(gòu)建采用什么樣的語(yǔ)法。這種擴(kuò)展通常并不創(chuàng)建新的組合音羞;?(?P<name>...)?是唯一的例外囱桨。 以下是目前支持的擴(kuò)展。
(?aiLmsux)
(?'a',?'i',?'L',?'m',?'s',?'u',?'x'?中的一個(gè)或多個(gè)) 這個(gè)組合匹配一個(gè)空字符串嗅绰;這些字符對(duì)正則表達(dá)式設(shè)置以下標(biāo)記?re.A?(只匹配ASCII字符),?re.I?(忽略大小寫(xiě)),?re.L?(語(yǔ)言依賴(lài)),?re.M?(多行模式),?re.S?(點(diǎn)dot匹配全部字符),?re.U?(Unicode匹配), and?re.X?(冗長(zhǎng)模式)舍肠。 (這些標(biāo)記在?模塊內(nèi)容?中描述) 如果你想將這些標(biāo)記包含在正則表達(dá)式中,這個(gè)方法就很有用窘面,免去了在?re.compile()?中傳遞?flag?參數(shù)翠语。標(biāo)記應(yīng)該在表達(dá)式字符串首位表示。
(?:…)
正則括號(hào)的非捕獲版本。 匹配在括號(hào)內(nèi)的任何正則表達(dá)式,但該分組所匹配的子字符串?不能?在執(zhí)行匹配后被獲取或是之后在模式中被引用。
(?imsx-imsx:...)
(Zero or more letters from the set?'i',?'m',?'s',?'x', optionally followed by?'-'?followed by one or more letters from the same set.) The letters set or removes the corresponding flags:?re.I?(ignore case),?re.M?(multi-line),?re.S?(dot matches all), and?re.X?(verbose), for the part of the expression. (The flags are described in?模塊內(nèi)容.)
3.6 新版功能.
(?P<name>…)
(命名組合)類(lèi)似正則組合,但是匹配到的子串組在外部是通過(guò)定義的?name?來(lái)獲取的剂府。組合名必須是有效的Python標(biāo)識(shí)符,并且每個(gè)組合名只能用一個(gè)正則表達(dá)式定義剩檀,只能定義一次澄干。一個(gè)符號(hào)組合同樣是一個(gè)數(shù)字組合,就像這個(gè)組合沒(méi)有被命名一樣跷跪。
命名組合可以在三種上下文中引用馋嗜。如果樣式是?(?P<quote>['"]).*?(?P=quote)?(也就是說(shuō),匹配單引號(hào)或者雙引號(hào)括起來(lái)的字符串):
引用組合 “quote” 的上下文引用方法
在正則式自身內(nèi)(?P=quote)?(如示)
\1
處理匹配對(duì)象?mm.group('quote')
m.end('quote')?(等)
傳遞到?re.sub()?里的?repl?參數(shù)中\(zhòng)g<quote>
\g<1>
\1
(?P=name)
反向引用一個(gè)命名組合吵瞻;它匹配前面那個(gè)叫?name?的命名組中匹配到的串同樣的字串葛菇。
(?#…)
注釋?zhuān)焕锩娴膬?nèi)容會(huì)被忽略。
(?=…)
匹配?…?的內(nèi)容橡羞,但是并不消費(fèi)樣式的內(nèi)容眯停。這個(gè)叫做?lookahead assertion。比如卿泽,?Isaac?(?=Asimov)?匹配?'Isaac?'?只有在后面是?'Asimov'?的時(shí)候莺债。
(?!…)
匹配?…?不符合的情況。這個(gè)叫?negative lookahead assertion?(前視取反)。比如說(shuō)齐邦,?Isaac?(?!Asimov)?只有后面?不?是?'Asimov'?的時(shí)候才匹配?'Isaac?'?椎侠。
(?<=…)
匹配字符串的當(dāng)前位置,它的前面匹配?…?的內(nèi)容到當(dāng)前位置措拇。這叫:dfn:positive lookbehind assertion?(正向后視斷定)我纪。?(?<=abc)def?會(huì)在?'abcdef'?中找到一個(gè)匹配,因?yàn)楹笠晻?huì)往后看3個(gè)字符并檢查是否包含匹配的樣式丐吓。包含的匹配樣式必須是定長(zhǎng)的浅悉,意思就是?abc?或?a|b?是允許的,但是?a*?和?a{3,4}?不可以券犁。注意以 positive lookbehind assertions 開(kāi)始的樣式仇冯,如?(?<=abc)def?,并不是從 a 開(kāi)始搜索族操,而是從 d 往回看的苛坚。你可能更加愿意使用?search()?函數(shù),而不是?match()?函數(shù):
>>>importre
>>>m=re.search('(?<=abc)def','abcdef')
>>>m.group(0)
'def'
這個(gè)例子搜索一個(gè)跟隨在連字符后的單詞:
>>>m=re.search(r'(?<=-)\w+','spam-egg')
>>>m.group(0)
'egg'
在 3.5 版更改:?添加定長(zhǎng)組合引用的支持色难。
(?<!…)
匹配當(dāng)前位置之前不是?…?的樣式泼舱。這個(gè)叫:dfn:negative lookbehind assertion?(后視斷定取非)。類(lèi)似正向后視斷定枷莉,包含的樣式匹配必須是定長(zhǎng)的娇昙。由 negative lookbehind assertion 開(kāi)始的樣式可以從字符串搜索開(kāi)始的位置進(jìn)行匹配。
(?(id/name)yes-pattern|no-pattern)
如果給定的?id?或?name?存在笤妙,將會(huì)嘗試匹配?yes-pattern?冒掌,否則就嘗試匹配?no-pattern,no-pattern?可選蹲盘,也可以被忽略股毫。比如,?(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)?是一個(gè)email樣式匹配召衔,將匹配?'<user@host.com>'?或?'user@host.com'?铃诬,但不會(huì)匹配?'<user@host.com'?,也不會(huì)匹配?'user@host.com>'苍凛。
由?'\'?和一個(gè)字符組成的特殊序列在以下列出趣席。 如果普通字符不是ASCII數(shù)位或者ASCII字母,那么正則樣式將匹配第二個(gè)字符醇蝴。比如宣肚,\$?匹配字符?'$'.
\number
匹配數(shù)字代表的組合。每個(gè)括號(hào)是一個(gè)組合悠栓,組合從1開(kāi)始編號(hào)霉涨。比如?(.+)?\1?匹配?'the?the'?或者?'55?55', 但不會(huì)匹配?'thethe'?(注意組合后面的空格)弧呐。這個(gè)特殊序列只能用于匹配前面99個(gè)組合。如果?number?的第一個(gè)數(shù)位是0嵌纲, 或者?number?是三個(gè)八進(jìn)制數(shù)俘枫,它將不會(huì)被看作是一個(gè)組合,而是八進(jìn)制的數(shù)字值逮走。在?'['?和?']'?字符集合內(nèi)鸠蚪,任何數(shù)字轉(zhuǎn)義都被看作是字符。
\A
只匹配字符串開(kāi)始师溅。
\b
匹配空字符串茅信,但只在單詞開(kāi)始或結(jié)尾的位置。一個(gè)單詞被定義為一個(gè)單詞字符的序列墓臭。注意蘸鲸,通常?\b?定義為?\w?和?\W?字符之間,或者?\w?和字符串開(kāi)始/結(jié)尾的邊界窿锉, 意思就是?r'\bfoo\b'?匹配?'foo',?'foo.',?'(foo)',?'bar?foo?baz'?但不匹配?'foobar'?或者?'foo3'酌摇。
默認(rèn)情況下,Unicode字母和數(shù)字是在Unicode樣式中使用的嗡载,但是可以用?ASCII?標(biāo)記來(lái)更改窑多。如果?LOCALE?標(biāo)記被設(shè)置的話,詞的邊界是由當(dāng)前語(yǔ)言區(qū)域設(shè)置決定的洼滚,\b?表示退格字符埂息,以便與Python字符串文本兼容。
\B
匹配空字符串遥巴,但?不?能在詞的開(kāi)頭或者結(jié)尾千康。意思就是?r'py\B'?匹配?'python',?'py3',?'py2', 但不匹配?'py',?'py.', 或者?'py!'.?\B?是?\b?的取非,所以Unicode樣式的詞語(yǔ)是由Unicode字母铲掐,數(shù)字或下劃線構(gòu)成的拾弃,雖然可以用?ASCII?標(biāo)志來(lái)改變。如果使用了?LOCALE?標(biāo)志迹炼,則詞的邊界由當(dāng)前語(yǔ)言區(qū)域設(shè)置砸彬。
\d對(duì)于 Unicode (str) 樣式:
Matches any Unicode decimal digit (that is, any character in Unicode character category [Nd]). This includes?[0-9], and also many other digit characters. If the?ASCII?flag is used only?[0-9]?is matched (but the flag affects the entire regular expression, so in such cases using an explicit?[0-9]?may be a better choice).
對(duì)于8位(bytes)樣式:
匹配任何十進(jìn)制數(shù),就是?[0-9]斯入。
\D
Matches any character which is not a decimal digit. This is the opposite of?\d. If the?ASCII?flag is used this becomes the equivalent of?[^0-9]?(but the flag affects the entire regular expression, so in such cases using an explicit?[^0-9]?may be a better choice).
\s對(duì)于 Unicode (str) 樣式:
Matches Unicode whitespace characters (which includes?[?\t\n\r\f\v], and also many other characters, for example the non-breaking spaces mandated by typography rules in many languages). If the?ASCII?flag is used, only?[?\t\n\r\f\v]?is matched (but the flag affects the entire regular expression, so in such cases using an explicit?[?\t\n\r\f\v]?may be a better choice).
對(duì)于8位(bytes)樣式:
匹配ASCII中的空白字符,就是?[?\t\n\r\f\v]?蛀蜜。
\S
Matches any character which is not a whitespace character. This is the opposite of?\s. If the?ASCII?flag is used this becomes the equivalent of?[^?\t\n\r\f\v]?(but the flag affects the entire regular expression, so in such cases using an explicit?[^?\t\n\r\f\v]?may be a better choice).
\w對(duì)于 Unicode (str) 樣式:
Matches Unicode word characters; this includes most characters that can be part of a word in any language, as well as numbers and the underscore. If the?ASCII?flag is used, only?[a-zA-Z0-9_]?is matched (but the flag affects the entire regular expression, so in such cases using an explicit?[a-zA-Z0-9_]?may be a better choice).
對(duì)于8位(bytes)樣式:
匹配ASCII字符中的數(shù)字和字母和下劃線刻两,就是?[a-zA-Z0-9_]?。如果設(shè)置了?LOCALE?標(biāo)記滴某,就匹配當(dāng)前語(yǔ)言區(qū)域的數(shù)字和字母和下劃線磅摹。
\W
Matches any character which is not a word character. This is the opposite of?\w. If the?ASCII?flag is used this becomes the equivalent of?[^a-zA-Z0-9_]?(but the flag affects the entire regular expression, so in such cases using an explicit?[^a-zA-Z0-9_]?may be a better choice). If the?LOCALE?flag is used, matches characters considered alphanumeric in the current locale and the underscore.
\Z
只匹配字符串尾滋迈。
絕大部分Python的標(biāo)準(zhǔn)轉(zhuǎn)義字符也被正則表達(dá)式分析器支持。:
\a????? \b????? \f????? \n
\r????? \t????? \u????? \U
\v????? \x????? \\
(注意?\b?被用于表示詞語(yǔ)的邊界户誓,它只在字符集合內(nèi)表示退格饼灿,比如?[\b]?。)
'\u'?and?'\U'?escape sequences are only recognized in Unicode patterns. In bytes patterns they are errors.
八進(jìn)制轉(zhuǎn)義包含為一個(gè)有限形式帝美。如果首位數(shù)字是 0碍彭, 或者有三個(gè)八進(jìn)制數(shù)位,那么就認(rèn)為它是八進(jìn)制轉(zhuǎn)義悼潭。其他的情況庇忌,就看作是組引用。對(duì)于字符串文本舰褪,八進(jìn)制轉(zhuǎn)義最多有三個(gè)數(shù)位長(zhǎng)皆疹。
在 3.3 版更改:?增加了?'\u'?和?'\U'?轉(zhuǎn)義序列。
在 3.6 版更改:?由?'\'?和一個(gè)ASCII字符組成的未知轉(zhuǎn)義會(huì)被看成錯(cuò)誤占拍。
模塊內(nèi)容
模塊定義了幾個(gè)函數(shù)略就,常量,和一個(gè)例外晃酒。有些函數(shù)是編譯后的正則表達(dá)式方法的簡(jiǎn)化版本(少了一些特性)残制。絕大部分重要的應(yīng)用,總是會(huì)先將正則表達(dá)式編譯掖疮,之后在進(jìn)行操作初茶。
在 3.6 版更改:?標(biāo)志常量現(xiàn)在是?RegexFlag?類(lèi)的實(shí)例,這個(gè)類(lèi)是?enum.IntFlag?的子類(lèi)浊闪。
re.compile(pattern,?flags=0)
Compile a regular expression pattern into a?regular expression object, which can be used for matching using its?match(),?search()?and other methods, described below.
這個(gè)表達(dá)式的行為可以通過(guò)指定?標(biāo)記?的值來(lái)改變恼布。值可以是以下任意變量,可以通過(guò)位的OR操作來(lái)結(jié)合(?|?操作符)搁宾。
序列
prog=re.compile(pattern)
result=prog.match(string)
等價(jià)于
result=re.match(pattern, string)
如果需要多次使用這個(gè)正則表達(dá)式的話折汞,使用?re.compile()?和保存這個(gè)正則對(duì)象以便復(fù)用,可以讓程序更加高效盖腿。
注解
通過(guò)?re.compile()?編譯后的樣式爽待,和模塊級(jí)的函數(shù)會(huì)被緩存, 所以少數(shù)的正則表達(dá)式使用無(wú)需考慮編譯的問(wèn)題翩腐。
re.Are.ASCII
讓?\w,?\W,?\b,?\B,?\d,?\D,?\s?和?\S?只匹配ASCII鸟款,而不是Unicode。這只對(duì)Unicode樣式有效茂卦,會(huì)被byte樣式忽略何什。相當(dāng)于前面語(yǔ)法中的內(nèi)聯(lián)標(biāo)志?(?a)?。
注意等龙,為了保持向后兼容处渣,?re.U?標(biāo)記依然存在(還有他的同義?re.UNICODE?和嵌入形式?(?u)?) 伶贰, 但是這些在 Python 3 是冗余的,因?yàn)槟J(rèn)字符串已經(jīng)是Unicode了(并且Unicode匹配不允許byte出現(xiàn))罐栈。
re.DEBUG
顯示編譯時(shí)的debug信息黍衙,沒(méi)有內(nèi)聯(lián)標(biāo)記。
re.Ire.IGNORECASE
進(jìn)行忽略大小寫(xiě)匹配荠诬;表達(dá)式如?[A-Z]?也會(huì)匹配小寫(xiě)字符琅翻。Unicode匹配(比如?ü?匹配?ü)同樣有用,除非設(shè)置了?re.ASCII?標(biāo)記來(lái)禁用非ASCII匹配浅妆。當(dāng)前語(yǔ)言區(qū)域不會(huì)改變這個(gè)標(biāo)記望迎,除非設(shè)置了?re.LOCALE?標(biāo)記。這個(gè)相當(dāng)于內(nèi)聯(lián)標(biāo)記?(?i)?凌外。
Note that when the Unicode patterns?[a-z]?or?[A-Z]?are used in combination with the?IGNORECASE?flag, they will match the 52 ASCII letters and 4 additional non-ASCII letters: ‘?’ (U+0130, Latin capital letter I with dot above), ‘?’ (U+0131, Latin small letter dotless i), ‘?’ (U+017F, Latin small letter long s) and ‘?’ (U+212A, Kelvin sign). If the?ASCII?flag is used, only letters ‘a(chǎn)’ to ‘z’ and ‘A’ to ‘Z’ are matched (but the flag affects the entire regular expression, so in such cases using an explicit?(?-i:[a-zA-Z])?may be a better choice).
re.Lre.LOCALE
由當(dāng)前語(yǔ)言區(qū)域決定?\w,?\W,?\b,?\B?和大小寫(xiě)敏感匹配辩尊。這個(gè)標(biāo)記只能對(duì)byte樣式有效。這個(gè)標(biāo)記不推薦使用康辑,因?yàn)檎Z(yǔ)言區(qū)域機(jī)制很不可靠摄欲,它一次只能處理一個(gè) “習(xí)慣”,而且只對(duì)8位字節(jié)有效疮薇。Unicode匹配在Python 3 里默認(rèn)啟用胸墙,并可以處理不同語(yǔ)言。 這個(gè)對(duì)應(yīng)內(nèi)聯(lián)標(biāo)記?(?L)?按咒。
在 3.6 版更改:?re.LOCALE?只能用于byte樣式迟隅,而且不能和?re.ASCII?一起用。
re.Mre.MULTILINE
設(shè)置以后励七,樣式字符?'^'?匹配字符串的開(kāi)始智袭,和每一行的開(kāi)始(換行符后面緊跟的符號(hào));樣式字符?'$'?匹配字符串尾掠抬,和每一行的結(jié)尾(換行符前面那個(gè)符號(hào))吼野。默認(rèn)情況下,’^’?匹配字符串頭两波,'$'?匹配字符串尾瞳步。對(duì)應(yīng)內(nèi)聯(lián)標(biāo)記?(?m)?。
re.Sre.DOTALL
讓?'.'?特殊字符匹配任何字符腰奋,包括換行符单起;如果沒(méi)有這個(gè)標(biāo)記,'.'?就匹配?除了?換行符的其他任意字符氛堕。對(duì)應(yīng)內(nèi)聯(lián)標(biāo)記?(?s)?馏臭。
re.Xre.VERBOSE
這個(gè)標(biāo)記允許你編寫(xiě)更具可讀性更友好的正則表達(dá)式。通過(guò)分段和添加注釋讼稚±ㄈ澹空白符號(hào)會(huì)被忽略,除非在一個(gè)字符集合當(dāng)中或者由反斜杠轉(zhuǎn)義锐想,或者在?*?,?(?:?or?(?P<…>?分組之內(nèi)帮寻。當(dāng)一個(gè)行內(nèi)有?#?不在字符集和轉(zhuǎn)義序列,那么它之后的所有字符都是注釋赠摇。
意思就是下面兩個(gè)正則表達(dá)式等價(jià)地匹配一個(gè)十進(jì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*")
對(duì)應(yīng)內(nèi)聯(lián)標(biāo)記?(?x)?固逗。
re.search(pattern,?string,?flags=0)
掃描整個(gè)?字符串?找到匹配樣式的第一個(gè)位置,并返回一個(gè)相應(yīng)的?匹配對(duì)象藕帜。如果沒(méi)有匹配烫罩,就返回一個(gè)?None?; 注意這和找到一個(gè)零長(zhǎng)度匹配是不同的洽故。
re.match(pattern,?string,?flags=0)
如果?string?開(kāi)始的0或者多個(gè)字符匹配到了正則表達(dá)式樣式贝攒,就返回一個(gè)相應(yīng)的?匹配對(duì)象?。 如果沒(méi)有匹配时甚,就返回?None?隘弊;注意它跟零長(zhǎng)度匹配是不同的。
注意即便是?MULTILINE?多行模式荒适,?re.match()?也只匹配字符串的開(kāi)始位置梨熙,而不匹配每行開(kāi)始。
如果你想定位?string?的任何位置刀诬,使用?search()?來(lái)替代(也可參考?search() vs. match()?)
re.fullmatch(pattern,?string,?flags=0)
如果整個(gè)?string?匹配到正則表達(dá)式樣式咽扇,就返回一個(gè)相應(yīng)的?匹配對(duì)象?。 否則就返回一個(gè)?None?陕壹;注意這跟零長(zhǎng)度匹配是不同的质欲。
3.4 新版功能.
re.split(pattern,?string,?maxsplit=0,?flags=0)
用?pattern?分開(kāi)?string?。 如果在?pattern?中捕獲到括號(hào)帐要,那么所有的組里的文字也會(huì)包含在列表里把敞。如果?maxsplit?非零, 最多進(jìn)行?maxsplit?次分隔榨惠, 剩下的字符全部返回到列表的最后一個(gè)元素奋早。
>>>
>>>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']
如果分隔符里有捕獲組合,并且匹配到字符串的開(kāi)始赠橙,那么結(jié)果將會(huì)以一個(gè)空字符串開(kāi)始耽装。對(duì)于結(jié)尾也是一樣
>>>
>>>re.split(r'(\W+)','...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
這樣的話,分隔組將會(huì)出現(xiàn)在結(jié)果列表中同樣的位置期揪。
注解
split()?doesn’t currently split a string on an empty pattern match. For example:
>>>
>>>re.split('x*','axbc')
['a', 'bc']
Even though?'x*'?also matches 0 ‘x’ before ‘a(chǎn)’, between ‘b’ and ‘c’, and after ‘c’, currently these matches are ignored. The correct behavior (i.e. splitting on empty matches too and returning?['',?'a',?'b',?'c',?'']) will be implemented in future versions of Python, but since this is a backward incompatible change, a?FutureWarning?will be raised in the meanwhile.
Patterns that can only match empty strings currently never split the string. Since this doesn’t match the expected behavior, a?ValueError?will be raised starting from Python 3.5:
>>>
>>>re.split("^$","foo\n\nbar\n", flags=re.M)
Traceback (most recent call last):
? File"<stdin>", line1, in <module>
?...
ValueError: split() requires a non-empty pattern match.
在 3.1 版更改:?增加了可選標(biāo)記參數(shù)掉奄。
在 3.5 版更改:?Splitting on a pattern that could match an empty string now raises a warning. Patterns that can only match empty strings are now rejected.
re.findall(pattern,?string,?flags=0)
對(duì)?string?返回一個(gè)不重復(fù)的?pattern?的匹配列表,?string?從左到右進(jìn)行掃描,匹配按找到的順序返回姓建。如果樣式里存在一到多個(gè)組诞仓,就返回一個(gè)組合列表;就是一個(gè)元組的列表(如果樣式里有超過(guò)一個(gè)組合的話)速兔∈茫空匹配也會(huì)包含在結(jié)果里。
注解
Due to the limitation of the current implementation the character following an empty match is not included in a next match, so?findall(r'^|\w+',?'two?words')?returns?['',?'wo',?'words']?(note missed “t”). This is changed in Python 3.7.
re.finditer(pattern,?string,?flags=0)
Return an?iterator?yielding?match objects?over all non-overlapping matches for the RE?pattern?in?string. The?string?is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result. See also the note about?findall().
re.sub(pattern,?repl,?string,?count=0,?flags=0)
Return the string obtained by replacing the leftmost non-overlapping occurrences of?pattern?in?string?by the replacement?repl. If the pattern isn’t found,?string?is returned unchanged.?repl?can be a string or a function; if it is a string, any backslash escapes in it are processed. That is,?\n?is converted to a single newline character,?\r?is converted to a carriage return, and so forth. Unknown escapes such as?\&?are left alone. Backreferences, such as?\6, are replaced with the substring matched by group 6 in the pattern. For example:
>>>
>>>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?是一個(gè)函數(shù)涣狗,那它會(huì)對(duì)每個(gè)非重復(fù)的?pattern?的情況調(diào)用谍婉。這個(gè)函數(shù)只能有一個(gè)?匹配對(duì)象?參數(shù),并返回一個(gè)替換后的字符串镀钓。比如
>>>
>>>defdashrepl(matchobj):
...???ifmatchobj.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'
樣式可以是一個(gè)字符串或者一個(gè)?樣式對(duì)象?穗熬。
The optional argument?count?is the maximum number of pattern occurrences to be replaced;?count?must be a non-negative integer. If omitted or zero, all occurrences will be replaced. Empty matches for the pattern are replaced only when not adjacent to a previous match, so?sub('x*',?'-',?'abc')?returns?'-a-b-c-'.
在字符串類(lèi)型的?repl?參數(shù)里,如上所述的轉(zhuǎn)義和向后引用中丁溅,\g<name>?會(huì)使用命名組合?name唤蔗,(在?(?P<name>…)?語(yǔ)法中定義)?\g<number>?會(huì)使用數(shù)字組;\g<2>?就是?\2唧瘾,但它避免了二義性措译,如?\g<2>0。?\20?就會(huì)被解釋為組20饰序,而不是組2后面跟隨一個(gè)字符?'0'领虹。向后引用?\g<0>?把?pattern?作為一整個(gè)組進(jìn)行引用。
在 3.1 版更改:?增加了可選標(biāo)記參數(shù)求豫。
在 3.5 版更改:?不匹配的組合替換為空字符串塌衰。
在 3.6 版更改:?pattern?中的未知轉(zhuǎn)義(由?'\'?和一個(gè) ASCII 字符組成)被視為錯(cuò)誤。
Deprecated since version 3.5, will be removed in version 3.7:?Unknown escapes in?repl?consisting of?'\'?and an ASCII letter now raise a deprecation warning and will be forbidden in Python 3.7.
re.subn(pattern,?repl,?string,?count=0,?flags=0)
行為與?sub()?相同蝠嘉,但是返回一個(gè)元組?(字符串,?替換次數(shù)).
在 3.1 版更改:?增加了可選標(biāo)記參數(shù)最疆。
在 3.5 版更改:?不匹配的組合替換為空字符串。
re.escape(pattern)
Escape all the characters in?pattern?except ASCII letters, numbers and?'_'. This is useful if you want to match an arbitrary literal string that may have regular expression metacharacters in it. For example:
>>>
>>>print(re.escape('python.exe'))
python\.exe
>>>legal_chars=string.ascii_lowercase+string.digits+"!#$%&'*+-.^_`|~:"
>>>print('[%s]+'%re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789\!\#\$\%\&\'\*\+\-\.\^_\`\|\~\:]+
>>>operators=['+','-','*','/','**']
>>>print('|'.join(map(re.escape,sorted(operators, reverse=True))))
\/|\-|\+|\*\*|\*
This functions must not be used for the replacement string in?sub()?and?subn(), only backslashes should be escaped. For example:
>>>
>>>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
在 3.3 版更改:?'_'?不再被轉(zhuǎn)義蚤告。
re.purge()
清除正則表達(dá)式緩存努酸。
exception?re.error(msg,?pattern=None,?pos=None)
raise?一個(gè)例外。當(dāng)傳遞到函數(shù)的字符串不是一個(gè)有效正則表達(dá)式的時(shí)候(比如杜恰,包含一個(gè)不匹配的括號(hào))或者其他錯(cuò)誤在編譯時(shí)或匹配時(shí)產(chǎn)生获诈。如果字符串不包含樣式匹配,是不會(huì)被視為錯(cuò)誤的心褐。錯(cuò)誤實(shí)例有以下附加屬性:
msg
未格式化的錯(cuò)誤消息舔涎。
pattern
正則表達(dá)式樣式。
pos
編譯失敗的?pattern?的位置索引(可以是?None?)逗爹。
lineno
對(duì)應(yīng)?pos?(可以是?None) 的行號(hào)亡嫌。
colno
對(duì)應(yīng)?pos?(可以是?None) 的列號(hào)。
在 3.5 版更改:?添加了附加屬性。
正則表達(dá)式對(duì)象 (正則對(duì)象)
編譯后的正則表達(dá)式對(duì)象支持以下方法和屬性:
regex.search(string[,?pos[,?endpos]])
掃描整個(gè)?string?尋找第一個(gè)匹配的位置挟冠, 并返回一個(gè)相應(yīng)的?匹配對(duì)象于购。如果沒(méi)有匹配,就返回?None?圃郊;注意它和零長(zhǎng)度匹配是不同的价涝。
可選的第二個(gè)參數(shù)?pos?給出了字符串中開(kāi)始搜索的位置索引女蜈;默認(rèn)為?0持舆,它不完全等價(jià)于字符串切片;?'^'?樣式字符匹配字符串真正的開(kāi)頭伪窖,和換行符后面的第一個(gè)字符逸寓,但不會(huì)匹配索引規(guī)定開(kāi)始的位置。
可選參數(shù)?endpos?限定了字符串搜索的結(jié)束覆山;它假定字符串長(zhǎng)度到?endpos?竹伸, 所以只有從?pos?到?endpos?-?1?的字符會(huì)被匹配。如果?endpos?小于?pos簇宽,就不會(huì)有匹配產(chǎn)生勋篓;另外,如果?rx?是一個(gè)編譯后的正則對(duì)象魏割,?rx.search(string,?0,?50)?等價(jià)于?rx.search(string[:50],?0)譬嚣。
>>>
>>>pattern=re.compile("d")
>>>pattern.search("dog")????# Match at index 0
<_sre.SRE_Match object; span=(0, 1), match='d'>
>>>pattern.search("dog",1)?# No match; search doesn't include the "d"
regex.match(string[,?pos[,?endpos]])
如果?string?的?開(kāi)始位置?能夠找到這個(gè)正則樣式的任意個(gè)匹配,就返回一個(gè)相應(yīng)的?匹配對(duì)象钞它。如果不匹配拜银,就返回?None?;注意它與零長(zhǎng)度匹配是不同的遭垛。
The optional?pos?and?endpos?parameters have the same meaning as for the?search()?method.
>>>
>>>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".
<_sre.SRE_Match object; span=(1, 2), match='o'>
If you want to locate a match anywhere in?string, use?search()?instead (see also?search() vs. match()).
regex.fullmatch(string[,?pos[,?endpos]])
如果整個(gè)?string?匹配這個(gè)正則表達(dá)式尼桶,就返回一個(gè)相應(yīng)的?匹配對(duì)象?。 否則就返回?None?锯仪; 注意跟零長(zhǎng)度匹配是不同的泵督。
The optional?pos?and?endpos?parameters have the same meaning as for the?search()?method.
>>>
>>>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.
<_sre.SRE_Match object; span=(1, 3), match='og'>
3.4 新版功能.
regex.split(string,?maxsplit=0)
等價(jià)于?split()?函數(shù),使用了編譯后的樣式庶喜。
regex.findall(string[,?pos[,?endpos]])
類(lèi)似函數(shù)?findall()?小腊, 使用了編譯后樣式,但也可以接收可選參數(shù)?pos?和?endpos?溃卡,限制搜索范圍溢豆,就像?search()。
regex.finditer(string[,?pos[,?endpos]])
類(lèi)似函數(shù)?finiter()?瘸羡, 使用了編譯后樣式漩仙,但也可以接收可選參數(shù)?pos?和?endpos?,限制搜索范圍,就像?search()队他。
regex.sub(repl,?string,?count=0)
等價(jià)于?sub()?函數(shù)卷仑,使用了編譯后的樣式。
regex.subn(repl,?string,?count=0)
等價(jià)于?subn()?函數(shù)麸折,使用了編譯后的樣式锡凝。
regex.flags
正則匹配標(biāo)記。這是可以傳遞給?compile()?的參數(shù)垢啼,任何?(?…)?內(nèi)聯(lián)標(biāo)記窜锯,隱性標(biāo)記比如?UNICODE?的結(jié)合。
regex.groups
捕獲組合的數(shù)量芭析。
regex.groupindex
映射由?(?P<id>)?定義的命名符號(hào)組合和數(shù)字組合的字典锚扎。如果沒(méi)有符號(hào)組,那字典就是空的馁启。
regex.pattern
The pattern string from which the RE object was compiled.
匹配對(duì)象
Match objects always have a boolean value of?True. Since?match()?and?search()?return?None?when there is no match, you can test whether there was a match with a simple?if?statement:
match=re.search(pattern, string)
ifmatch:
??? process(match)
匹配對(duì)象支持以下方法和屬性:
match.expand(template)
Return the string obtained by doing backslash substitution on the template string?template, as done by the?sub()?method. Escapes such as?\n?are converted to the appropriate characters, and numeric backreferences (\1,?\2) and named backreferences (\g<1>,?\g<name>) are replaced by the contents of the corresponding group.
在 3.5 版更改:?不匹配的組合替換為空字符串驾孔。
match.group([group1,?...])
返回一個(gè)或者多個(gè)匹配的子組。如果只有一個(gè)參數(shù)惯疙,結(jié)果就是一個(gè)字符串翠勉,如果有多個(gè)參數(shù),結(jié)果就是一個(gè)元組(每個(gè)參數(shù)對(duì)應(yīng)一個(gè)項(xiàng))霉颠,如果沒(méi)有參數(shù)对碌,組1默認(rèn)到0(整個(gè)匹配都被返回)。 如果一個(gè)組N 參數(shù)值為 0掉分,相應(yīng)的返回值就是整個(gè)匹配字符串俭缓;如果它是一個(gè)范圍 [1..99],結(jié)果就是相應(yīng)的括號(hào)組字符串酥郭。如果一個(gè)組號(hào)是負(fù)數(shù)华坦,或者大于樣式中定義的組數(shù),一個(gè)?IndexError?索引錯(cuò)誤就?raise不从。如果一個(gè)組包含在樣式的一部分惜姐,并被匹配多次,就返回最后一個(gè)匹配椿息。:
>>>
>>>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')
如果正則表達(dá)式使用了?(?P<name>…)?語(yǔ)法歹袁,?groupN?參數(shù)就也可能是命名組合的名字。如果一個(gè)字符串參數(shù)在樣式中未定義為組合名寝优,一個(gè)?IndexError?就?raise条舔。
一個(gè)相對(duì)復(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'
命名組合同樣可以通過(guò)索引值引用
>>>
>>>m.group(1)
'Malcolm'
>>>m.group(2)
'Reynolds'
如果一個(gè)組匹配成功多次,就只返回最后一個(gè)匹配
>>>
>>>m=re.match(r"(..)+","a1b2c3")?# Matches 3 times.
>>>m.group(1)???????????????????????# Returns only the last match.
'c3'
match.__getitem__(g)
這個(gè)等價(jià)于?m.group(g)乏矾。這允許更方便的引用一個(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'
3.6 新版功能.
match.groups(default=None)
返回一個(gè)元組孟抗,包含所有匹配的子組迁杨,在樣式中出現(xiàn)的從1到任意多的組合。?default?參數(shù)用于不參與匹配的情況凄硼,默認(rèn)為?None铅协。
例如
>>>
>>>m=re.match(r"(\d+)\.(\d+)","24.1632")
>>>m.groups()
('24', '1632')
如果我們使小數(shù)點(diǎn)可選,那么不是所有的組都會(huì)參與到匹配當(dāng)中摊沉。這些組合默認(rèn)會(huì)返回一個(gè)?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)
返回一個(gè)字典说墨,包含了所有的?命名?子組骏全。key就是組名。?default?參數(shù)用于不參與匹配的組合婉刀;默認(rèn)為?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?匹配到的字串的開(kāi)始和結(jié)束標(biāo)號(hào)。group?默認(rèn)為0(意思是整個(gè)匹配的子串)突颊。如果?group?存在,但未產(chǎn)生匹配潘悼,就返回?-1?律秃。對(duì)于一個(gè)匹配對(duì)象?m, 和一個(gè)未參與匹配的組?g?治唤,組?g?(等價(jià)于?m.group(g))產(chǎn)生的匹配是
m.string[m.start(g):m.end(g)]
注意?m.start(group)?將會(huì)等于?m.end(group)?棒动,如果?group?匹配一個(gè)空字符串的話。比如宾添,在?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 一個(gè)?IndexError?例外。
這個(gè)例子會(huì)從email地址中移除掉?remove_this
>>>
>>>email="tony@tiremove_thisger.net"
>>>m=re.search("remove_this", email)
>>>email[:m.start()]+email[m.end():]
match.span([group])
對(duì)于一個(gè)匹配?m?缕陕, 返回一個(gè)二元組?(m.start(group),?m.end(group))?粱锐。 注意如果?group?沒(méi)有在這個(gè)匹配中,就返回?(-1,?-1)?扛邑。group?默認(rèn)為0怜浅,就是整個(gè)匹配。
match.pos
The value of?pos?which was passed to the?search()?or?match()?method of a?regex object. This is the index into the string at which the RE engine started looking for a match.
match.endpos
The value of?endpos?which was passed to the?search()?or?match()?method of a?regex object. This is the index into the string beyond which the RE engine will not go.
match.lastindex
捕獲組的最后一個(gè)匹配的整數(shù)索引值蔬崩,或者?None?如果沒(méi)有匹配產(chǎn)生的話恶座。比如,對(duì)于字符串?'ab'沥阳,表達(dá)式?(a)b,?((a)(b)), 和?((ab))?將得到?lastindex?==?1?跨琳, 而?(a)(b)?會(huì)得到?lastindex?==?2?。
match.lastgroup
最后一個(gè)匹配的命名組名字桐罕,或者?None?如果沒(méi)有產(chǎn)生匹配的話脉让。
match.re
The?regular expression object?whose?match()?or?search()?method produced this match instance.
match.string
The string passed to?match()?or?search().
正則表達(dá)式例子
檢查對(duì)子
在這個(gè)例子里樟氢,我們使用以下輔助函數(shù)來(lái)更好的顯示匹配對(duì)象:
defdisplaymatch(match):
???ifmatchisNone:
???????returnNone
???return'<Match:%r, groups=%r>'%(match.group(), match.groups())
假設(shè)你在寫(xiě)一個(gè)撲克程序,一個(gè)玩家的一手牌為五個(gè)字符的串侠鳄,每個(gè)字符表示一張牌埠啃,”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"?博秫,包含了一個(gè)對(duì)子潦牛,或者兩張同樣數(shù)值的牌。要用正則表達(dá)式匹配它挡育,應(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',)>"
To find out what card the pair consists of, one could use the?group()?method of the match object in the following manner:
>>>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>", line1, in <module>
??? re.match(r".*(.).*\1","718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>>pair.match("354aa").group(1)
'a'
模擬 scanf()
Python 目前沒(méi)有一個(gè)類(lèi)似c函數(shù)?scanf()?的替代品巴碗。正則表達(dá)式通常比?scanf()?格式字符串要更強(qiáng)大一些,但也帶來(lái)更多復(fù)雜性即寒。下面的表格提供了?scanf()?格式符和正則表達(dá)式大致相同的映射橡淆。
scanf()?格式符正則表達(dá)式
%c.
%5c.{5}
%d[-+]?\d+
%e,?%E,?%f,?%g[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?
%i[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)
%o[-+]?[0-7]+
%s\S+
%u\d+
%x,?%X[-+]?(0[xX])?[\dA-Fa-f]+
從文件名和數(shù)字提取字符串
/usr/sbin/sendmail-0errors,4warnings
你可以使用?scanf()?格式化
%s-%d errors,%d warnings
等價(jià)的正則表達(dá)式是:
(\S+)-(\d+) errors, (\d+) warnings
search() vs. match()
Python 提供了兩種不同的操作:基于?re.match()?檢查字符串開(kāi)頭,或者?re.search()?檢查字符串的任意位置(默認(rèn)Perl中的行為)母赵。
例如
>>>
>>>re.match("c","abcdef")???# No match
>>>re.search("c","abcdef")??# Match
<_sre.SRE_Match object; span=(2, 3), match='c'>
在?search()?中逸爵,可以用?'^'?作為開(kāi)始來(lái)限制匹配到字符串的首位
>>>
>>>re.match("c","abcdef")???# No match
>>>re.search("^c","abcdef")?# No match
>>>re.search("^a","abcdef")?# Match
<_sre.SRE_Match object; span=(0, 1), match='a'>
注意?MULTILINE?多行模式中函數(shù)?match()?只匹配字符串的開(kāi)始,但使用?search()?和以?'^'?開(kāi)始的正則表達(dá)式會(huì)匹配每行的開(kāi)始
>>>
>>>re.match('X','A\nB\nX', re.MULTILINE)?# No match
>>>re.search('^X','A\nB\nX', re.MULTILINE)?# Match
<_sre.SRE_Match object; span=(4, 5), match='X'>
建立一個(gè)電話本
split()?將字符串用參數(shù)傳遞的樣式分隔開(kāi)凹嘲。這個(gè)方法對(duì)于轉(zhuǎn)換文本數(shù)據(jù)到易讀而且容易修改的數(shù)據(jù)結(jié)構(gòu)师倔,是很有用的,如下面的例子證明周蹭。
首先趋艘,這里是輸入。通常是一個(gè)文件凶朗,這里我們用三引號(hào)字符串語(yǔ)法
>>>
>>>text="""Ross McFluff: 834.345.1254 155 Elm Street
...
...Ronald Heathmore: 892.345.3428 436 Finley Avenue
...Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
...Heather Albrecht: 548.326.4584 919 Park Place"""
條目用一個(gè)或者多個(gè)換行符分開(kāi)〈呻剩現(xiàn)在我們將字符串轉(zhuǎn)換為一個(gè)列表玄渗,每個(gè)非空行都有一個(gè)條目:
>>>entries=re.split("\n+", text)
>>>entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
最終乖坠,將每個(gè)條目分割為一個(gè)由名字、姓氏勒极、電話號(hào)碼和地址組成的列表遇八。我們?yōu)?split()?使用了?maxsplit?形參矛绘,因?yàn)榈刂分邪斜晃覀冏鳛榉指钅J降目崭穹?
>>>[re.split(":? ", entry,3)forentryinentries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
:??樣式匹配姓后面的冒號(hào),因此它不出現(xiàn)在結(jié)果列表中刃永。如果?maxsplit?設(shè)置為?4?货矮,我們還可以從地址中獲取到房間號(hào):
>>>[re.split(":? ", entry,4)forentryinentries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
文字整理
sub()?替換字符串中出現(xiàn)的樣式的每一個(gè)實(shí)例。這個(gè)例子證明了使用?sub()?來(lái)整理文字斯够,或者隨機(jī)化每個(gè)字符的位置囚玫,除了首位和末尾字符
>>>
>>>defrepl(m):
...??? inner_word=list(m.group(2))
...??? random.shuffle(inner_word)
...???returnm.group(1)+"".join(inner_word)+m.group(3)
>>>text="Professor Abdolmalek, please report your absences promptly."
>>>re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>>re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
找到所有副詞
findall()?匹配樣式?所有?的出現(xiàn)喧锦,不僅是像?search()?中的第一個(gè)匹配。比如抓督,如果一個(gè)作者希望找到文字中的所有副詞燃少,他可能會(huì)按照以下方法用?findall()
>>>
>>>text="He was carefully disguised but captured quickly by police."
>>>re.findall(r"\w+ly", text)
['carefully', 'quickly']
找到所有副詞和位置
如果需要匹配樣式的更多信息,?finditer()?可以起到作用铃在,它提供了?匹配對(duì)象?作為返回值阵具,而不是字符串。繼續(xù)上面的例子定铜,如果一個(gè)作者希望找到所有副詞和它的位置阳液,可以按照下面方法使用?finditer()
>>>
>>>text="He was carefully disguised but captured quickly by police."
>>>forminre.finditer(r"\w+ly", text):
...???print('%02d-%02d:%s'%(m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly
原始字符記法
原始字符串記法 (r"text") 保持正則表達(dá)式正常。否則揣炕,每個(gè)正則式里的反斜杠('\') 都必須前綴一個(gè)反斜杠來(lái)轉(zhuǎn)義帘皿。比如,下面兩行代碼功能就是完全一致的
>>>
>>>re.match(r"\W(.)\1\W"," ff ")
<_sre.SRE_Match object; span=(0, 4), match=' ff '>
>>>re.match("\\W(.)\\1\\W"," ff ")
<_sre.SRE_Match object; span=(0, 4), match=' ff '>
當(dāng)需要匹配一個(gè)字符反斜杠畸陡,它必須在正則表達(dá)式中轉(zhuǎn)義鹰溜。在原始字符串記法,就是?r"\\"罩锐。否則就必須用?"\\\\"奉狈,來(lái)表示同樣的意思
>>>
>>>re.match(r"\\",r"\\")
<_sre.SRE_Match object; span=(0, 1), match='\\'>
>>>re.match("\\\\",r"\\")
<_sre.SRE_Match object; span=(0, 1), match='\\'>
寫(xiě)一個(gè)詞法分析器
一個(gè)?詞法器或詞法分析器?分析字符串,并分類(lèi)成目錄組涩惑。 這是寫(xiě)一個(gè)編譯器或解釋器的第一步。
文字目錄是由正則表達(dá)式指定的桑驱。這個(gè)技術(shù)是通過(guò)將這些樣式合并為一個(gè)主正則式竭恬,并且循環(huán)匹配來(lái)實(shí)現(xiàn)的
importcollections
importre
Token=collections.namedtuple('Token', ['type','value','line','column'])
deftokenize(code):
??? keywords={'IF','THEN','ENDIF','FOR','NEXT','GOSUB','RETURN'}
??? token_specification=[
??????? ('NUMBER',??r'\d+(\.\d*)?'),?# Integer or decimal number
??????? ('ASSIGN',??r':='),??????????# Assignment operator
??????? ('END',?????r';'),???????????# Statement terminator
??????? ('ID',??????r'[A-Za-z]+'),???# Identifiers
??????? ('OP',??????r'[+\-*/]'),?????# Arithmetic operators
??????? ('NEWLINE',?r'\n'),??????????# Line endings
??????? ('SKIP',????r'[ \t]+'),??????# Skip over spaces and tabs
??????? ('MISMATCH',r'.'),???????????# Any other character
??? ]
??? tok_regex='|'.join('(?P<%s>%s)'%pairforpairintoken_specification)
??? line_num=1
??? line_start=0
???formoinre.finditer(tok_regex, code):
??????? kind=mo.lastgroup
??????? value=mo.group()
??????? column=mo.start()-line_start
???????ifkind=='NUMBER':
??????????? value=float(value)if'.'invalueelseint(value)
???????elifkind=='ID'andvalueinkeywords:
??????????? kind=value
???????elifkind=='NEWLINE':
??????????? line_start=mo.end()
??????????? line_num+=1
???????????continue
???????elifkind=='SKIP':
???????????continue
???????elifkind=='MISMATCH':
???????????raiseRuntimeError(f'{value!r}unexpected on line{line_num}')
???????yieldToken(kind, value, line_num, column)
statements='''
??? IF quantity THEN
??????? total := total + price * quantity;
??????? tax := price * 0.05;
??? ENDIF;
'''
fortokenintokenize(statements):
???print(token)
這個(gè)詞法器產(chǎn)生以下輸出
Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)