天天看點

Python正規表達式指南

正規表達式并不是python的一部分。正規表達式是用于處理字元串的強大工具,擁有自己獨特的文法以及一個獨立的處理引擎,效率上可能不如str自帶的方法,但功能十分強大。得益于這一點,在提供了正規表達式的語言裡,正規表達式的文法都是一樣的,差別隻在于不同的程式設計語言實作支援的文法數量不同;但不用擔心,不被支援的文法通常是不常用的部分。如果已經在其他語言裡使用過正規表達式,隻需要簡單看一看就可以上手了。

下圖展示了使用正規表達式進行比對的流程: 

Python正規表達式指南

正規表達式的大緻比對過程是:依次拿出表達式和文本中的字元比較,如果每一個字元都能比對,則比對成功;一旦有比對不成功的字元則比對失敗。如果表達式中有量詞或邊界,這個過程會稍微有一些不同,但也是很好了解的,看下圖中的示例以及自己多使用幾次就能明白。

下圖列出了python支援的正規表達式元字元和文法:   

Python正規表達式指南

正規表達式通常用于在文本中查找比對的字元串。python裡數量詞預設是貪婪的(在少數語言裡也可能是預設非貪婪),總是嘗試比對盡可能多的字元;非貪婪的則相反,總是嘗試比對盡可能少的字元。例如:正規表達式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非貪婪的數量詞"ab*?",将找到"a"。

與大多數程式設計語言相同,正規表達式裡使用"\"作為轉義字元,這就可能造成反斜杠困擾。假如你需要比對文本中的字元"\",那麼使用程式設計語言表示的正規表達式裡将需要4個反斜杠"\\\\":前兩個和後兩個分别用于在程式設計語言裡轉義成反斜杠,轉換成兩個反斜杠後再在正規表達式裡轉義成一個反斜杠。python裡的原生字元串很好地解決了這個問題,這個例子中的正規表達式可以使用r"\\"表示。同樣,比對一個數字的"\\d"可以寫成r"\d"。有了原生字元串,你再也不用擔心是不是漏寫了反斜杠,寫出來的表達式也更直覺。

正規表達式提供了一些可用的比對模式,比如忽略大小寫、多行比對等,這部分内容将在pattern類的工廠方法re.compile(pattern[, flags])中一起介紹。

python通過re子產品提供對正規表達式的支援。使用re的一般步驟是先将正規表達式的字元串形式編譯為pattern執行個體,然後使用pattern執行個體處理文本并獲得比對結果(一個match執行個體),最後使用match執行個體獲得資訊,進行其他的操作。

re.compile(strpattern[, flag]):

這個方法是pattern類的工廠方法,用于将字元串形式的正規表達式編譯為pattern對象。 第二個參數flag是比對模式,取值可以使用按位或運算符'|'表示同時生效,比如re.i | re.m。另外,你也可以在regex字元串中指定模式,比如re.compile('pattern', re.i | re.m)與re.compile('(?im)pattern')是等價的。

可選值有:

re.i(re.ignorecase): 忽略大小寫(括号内是完整寫法,下同)

re.m(multiline): 多行模式,改變'^'和'$'的行為(參見上圖)

re.s(dotall): 點任意比對模式,改變'.'的行為

re.l(locale): 使預定字元類 \w \w \b \b \s \s 取決于目前區域設定

re.u(unicode): 使預定字元類 \w \w \b \b \s \s \d \d 取決于unicode定義的字元屬性

re.x(verbose): 詳細模式。這個模式下正規表達式可以是多行,忽略空白字元,并可以加入注釋。以下兩個正規表達式是等價的:

re提供了衆多子產品方法用于完成正規表達式的功能。這些方法可以使用pattern執行個體的相應方法替代,唯一的好處是少寫一行re.compile()代碼,但同時也無法複用編譯後的pattern對象。這些方法将在pattern類的執行個體方法部分一起介紹。如上面這個例子可以簡寫為:

re子產品還提供了一個方法escape(string),用于将string中的正規表達式元字元如*/+/?等之前加上轉義符再傳回,在需要大量比對元字元時有那麼一點用。

match對象是一次比對的結果,包含了很多關于此次比對的資訊,可以使用match提供的可讀屬性或方法來擷取這些資訊。

屬性:

string: 比對時使用的文本。

re: 比對時使用的pattern對象。

pos: 文本中正規表達式開始搜尋的索引。值與pattern.match()和pattern.seach()方法的同名參數相同。

endpos: 文本中正規表達式結束搜尋的索引。值與pattern.match()和pattern.seach()方法的同名參數相同。

lastindex: 最後一個被捕獲的分組在文本中的索引。如果沒有被捕獲的分組,将為none。

lastgroup: 最後一個被捕獲的分組的别名。如果這個分組沒有别名或者沒有被捕獲的分組,将為none。

方法:

group([group1, …]): 

獲得一個或多個分組截獲的字元串;指定多個參數時将以元組形式傳回。group1可以使用編号也可以使用别名;編号0代表整個比對的子串;不填寫參數時,傳回group(0);沒有截獲字元串的組傳回none;截獲了多次的組傳回最後一次截獲的子串。

groups([default]): 

以元組形式傳回全部分組截獲的字元串。相當于調用group(1,2,…last)。default表示沒有截獲字元串的組以這個值替代,預設為none。

groupdict([default]): 

傳回以有别名的組的别名為鍵、以該組截獲的子串為值的字典,沒有别名的組不包含在内。default含義同上。

start([group]): 

傳回指定的組截獲的子串在string中的起始索引(子串第一個字元的索引)。group預設值為0。

end([group]): 

傳回指定的組截獲的子串在string中的結束索引(子串最後一個字元的索引+1)。group預設值為0。

span([group]): 

傳回(start(group), end(group))。

expand(template): 

将比對到的分組代入template中然後傳回。template中可以使用\id或\g<id>、\g<name>引用分組,但不能使用編号0。\id與\g<id>是等價的;但\10将被認為是第10個分組,如果你想表達\1之後是字元'0',隻能使用\g<1>0。

pattern對象是一個編譯好的正規表達式,通過pattern提供的一系列方法可以對文本進行比對查找。

pattern不能直接執行個體化,必須使用re.compile()進行構造。

pattern提供了幾個可讀屬性用于擷取表達式的相關資訊:

pattern: 編譯時用的表達式字元串。

flags: 編譯時用的比對模式。數字形式。

groups: 表達式中分組的數量。

groupindex: 以表達式中有别名的組的别名為鍵、以該組對應的編号為值的字典,沒有别名的組不包含在内。

re.match與re.search的差別

re.match隻比對字元串的開始,如果字元串開始不符合正規表達式,則比對失敗,函數傳回none;而re.search比對整個字元串,直到找到一個

執行個體方法[ | re子產品方法]:

match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]): 

這個方法将從string的pos下标處起嘗試比對pattern;如果pattern結束時仍可比對,則傳回一個match對象;如果比對過程中pattern無法比對,或者比對未結束就已到達endpos,則傳回none。

pos和endpos的預設值分别為0和len(string);re.match()無法指定這兩個參數,參數flags用于編譯pattern時指定比對模式。 

注意:這個方法并不是完全比對。當pattern結束時若string還有剩餘字元,仍然視為成功。想要完全比對,可以在表達式末尾加上邊界比對符'$'。 

示例參見2.1小節。

search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):

這個方法用于查找字元串中可以比對成功的子串。從string的pos下标處起嘗試比對pattern,如果pattern結束時仍可比對,則傳回一個match對象;若無法比對,則将pos加1後重新嘗試比對;直到pos=endpos時仍無法比對則傳回none。

pos和endpos的預設值分别為0和len(string));re.search()無法指定這兩個參數,參數flags用于編譯pattern時指定比對模式。

split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):

按照能夠比對的子串将string分割後傳回清單。maxsplit用于指定最大分割次數,不指定将全部分割。

findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):

搜尋string,以清單形式傳回全部能比對的子串。

finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):

搜尋string,傳回一個順序通路每一個比對結果(match對象)的疊代器。

sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):

使用repl替換string中每一個比對的子串後傳回替換後的字元串。 

當repl是一個字元串時,可以使用\id或\g<id>、\g<name>引用分組,但不能使用編号0。 

當repl是一個方法時,這個方法應當隻接受一個參數(match對象),并傳回一個字元串用于替換(傳回的字元串中不能再引用分組)。 

count用于指定最多替換次數,不指定時全部替換。

subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):

傳回 (sub(repl, string[, count]), 替換次數)。