Python中的Regex(1)

來源:互聯網
上載者:User
文章目錄
  • 匹配字元

 

寫這個系列是為了整理在Python中學習Regex的知識。其實在Linux Shell、PHP以及Qt的學習中都接觸過Regex,但是由於筆記做得不好,所以經常到了使用的時候翻來翻去,很是麻煩,所以把知識梳理一下。本文主要翻譯自Python標準庫手冊中的指南,但是沒有逐字句地翻譯,它比標準庫中的re模組相應介紹要簡單一些,也更容易看懂。

----------------------------------

Regex入門

本文檔介紹使用Python中的re模組實現Regex,它比Python庫手冊中的相應章節相對容易一些。

引言

Re模組在Python1.5中加入,它提供了一個Perl風格的Regex功能。更早版本的Python使用的是regex模組,它提供的是Emacs風格的匹配。在Python2.5中,regex模組被移除。

 

Regex(Regular expression,又稱為RE、regexe或regex pattern)是一個小巧、高度特化的編程方法,它內嵌在Python中,通過re模組實現。使用這個方法可以匹配特定格式的字串,包括英語句子、電子郵件地址、TeX命令等等,可以檢查字串是否符合該格式,或在字串中尋找符合該格式的子串,也可以按照格式修改或分割字串。

 

 

Regex的“格式”(pattern)在運行時被由C語言寫成的匹配引擎轉換成位元組碼。對於進階應用程式,應當注意該引擎如何產生給定的Regex,並用特定方式書寫該運算式以產生更高效的位元組碼。不過,本文檔不涉及最佳化的問題,因為這需要對匹配引擎的內部工作原理有較好的理解。

 

Regex小巧且嚴格,所以不是所有的字串處理都要使用它;有些問題用Regex可以解決,但會讓問題變得複雜。在這些情況下,就不要使用Regex處理。儘管使用Python編寫的代碼比精巧設計的Regex慢,但它更易於理解。

 

簡單的格式

 

我們從最簡單的Regex開始學習。由於它主要用來處理字串,我們將首先學習最普遍的情況:匹配字元。電腦科學以Regex為基礎,關於它的詳細解釋可以參考關於書寫編譯器的幾乎任何課本。

 

匹配字元

 

大多數字母和符號可以匹配自身,可以將匹配模式選擇為大小寫敏感或不敏感,詳細內容見後。

 

這條規範有一個例外:有一些字元是特殊的“元字元”,不能匹配自身,它們表示非常規的意思,或者能夠通過重複或者改變其意思影響Regex的其他成分。本文檔專註於討論不同的元字元及其含義。

 

下面是這些元字元,它們的意思該在本文以後的部分加以介紹。

. ^ $ * + ? { } [ ] \ | ( )

 

首先來看[和]。它們用來表示一個字元的集合,集合內的任意一個字元都可以參與匹配,其中字元可以單獨列出來,或者用-來表示範圍。例如,[abc]將匹配其中的任何一個字元a、b或c,它等同於用範圍表示的[a-c]。如果匹配任何小寫字母,可以寫成[a-z]。

 

在[]中的元字元不起作用。如[akm$]將匹配a、k、m和$:$雖然是一個元字元,但是在這個集合中失去了特殊意義。

 

可以通過取補的方式匹配不在集合中的字元,方法是在該集合內的最前面加^,如果加在整個集合的前面則會匹配^。例如,[^5]將匹配除了5的任何字元。

 

最常用的元字元是反斜線\。在Python中,字元前加\表示特殊含義;它也可以用於元字元前表示去除元字元的特殊含義。例如,如果試圖匹配[或\,可以分別通過\[和\\來實現。

 

一些特殊序列以\開始,表示一些常用的預定義字串,如下所示:

 

\d

十進位數字,相當於[0-9]

\D

非十進位數字,相當於[^0-9]

\s

空白字元,相當於[\t\n\r\v]

\S

非空白字元,相當於[^\t\n\r\f\v]

\w

字母+數字,相當於[a-zA-Z0-9]

\W

非字母非數字,相當於[^a-zA-Z0-9]

這些特殊序列可以在集合中使用。如[\s,.]匹配任何空白字元、,或者.。

 

本節中最後一個元字元是.,它匹配除新行外的任何字元(在可選用的模組(re.DOTALL)中也可以匹配新行)。當試圖匹配任何字元時使用.。

 

多次匹配

 

匹配不同的字元集合是字串中的函數無法完成而Regex可以完成的第一件事,但如果僅僅如此,Regex還顯得功能簡陋。它另外一個功能是可以匹配特定次數的字元。

 

多次匹配的第一個元字元是*,它不是去匹配字元本身,而是表示前一個字元可以匹配0次或多次。例如ca*t將匹配ct(0次)、cat(1次)、caaat(3次)或更多。由於C語言中整型長度的限制,Regex的匹配引擎內部規定不能超過20億次的匹配,當然你可能並沒有足夠的記憶體去儲存這麼長的字串,所以不用理會這個限定。

 

*的匹配是“貪婪”的:當匹配時,引擎會試圖匹配更多次的字元;如果在較多次數下的匹配不成功(格式中的下一部分不能匹配時),才會試圖匹配較少的重複次數。

 

逐步講解的例子會使這種設計看上去合理。考慮a[bcd]*b,它匹配以a開始,中間含有0次或多次的b、c或者d,並最終以b結束。在字串abcbd中的匹配過程如下:

步驟 已匹配 說明
1 a a存在于格式中。
2 abcbd 引擎匹配了[bcd]*,試圖匹配盡量多次數,從而達到了字串尾。
3 匹配失敗 引擎試圖匹配b,但當前位置為字串的串尾,所以匹配失敗。
4 abcb 回頭重新匹配,使[bcd]*匹配次數在上次匹配的基礎上減1。
5 匹配失敗 再次試圖匹配b,但是當前位置為最後一個字元d,匹配失敗。
6 abc 回頭再次重新匹配,這次[bcd]*只匹配到bc。
7 abcb

嘗試匹配b,這次當前位置上為b,匹配成功。

到達Regex的結尾時,匹配abcb成功。以上過程表明“貪婪匹配”如果失敗,則會一次重新匹配儘可能多次的格式,直到嘗試匹配0次[bcd]*,如果在0次匹配的情況下後續字元依然無法匹配,則字元匹配失敗。

 

另外一個重複匹配的元字元是+,它匹配一次或者多次。注意*和+的區別。

 

另外,?表示匹配0次或1次,可以把它想像成某種可選擇性的場合,如home-?brew可以匹配homebrew或home-brew。

 

最常用的匹配次數運算式為{m,n},其中m和n為十進位數字,表示最少重複m次最多重複n次。例如a/{1,3}b可以匹配a/b、a//b和a///b,而對a////b不能匹配。M和n中的一個可以省略掉:省略掉m表示最少匹配0次,省略掉n表示最多匹配無窮次(實際上是20億次)。

 

很容易看出{0,}與*意義相同,類似地,{1,}與+、{0,1}與?意義都相同。這種情況下用單個字元更容易書寫,可讀性也更好。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.