Python——正則表達式(1)

本文譯自官方文檔:Regular Expression HOWTOhtml

全文下載:Python正則表達式基礎python

=========================================================================================程序員

摘要
正則表達式

本篇文檔是在Python中經過re模塊使用正則表達式的引導手冊,提供了一個比參考類庫相應部分更詳細的介紹。
數據庫

=========================================================================================學習

1.簡介
優化

正則表達式(也稱爲REs,regexes,或者regex  patterns)本質上是一個被嵌入到Python中的一個精細的、高度專業化的程序語言,並經過re模塊提供給程序員使用。使用正則表達式,你須要爲那些你想要匹配的字符串集合定製一些規則;這些集合可能包含英文句子、郵箱地址、TeX命令或者任何你想要的東西。而後你就會問相似於這樣的問題:「這個字符串匹配這個模式嗎?」或者「在這個字符串中有適合的模式來匹配嗎?」你可使用正則表達式去修改一個字符串或者用各類各樣的方式去分割字符串。spa


正則表達式模式被編譯成一系列的字節碼,而後由一個用C語言寫的匹配引擎執行。對於高級的應用,你必需要注意對於一個給定的RE,引擎是如何執行的,並經過必定的方式來編寫RE以便這些字節碼運行地更快。但本篇文檔不包含RE優化的內容,由於這些須要你對引擎內核有一個很好的理解。.net


正則表達式語言相對較小,也比較嚴格,因此並非全部的字符串處理任務均可以用正則表達式完成。有些任務能夠用正則表達式作,可是表達式很是複雜。在這些狀況下,你最好經過常規Python代碼完成任務,雖然Python代碼可能會比精心編寫的正則表達式運行速度要慢,可是相對來講,它更好理解。
code

=========================================================================================

2.簡單的模式

咱們從學習最簡單的正則表達式開始。因爲正則表達式常被用於處理字符串,因此咱們由最多見的任務入手:字符匹配。


對於計算機科學中潛在的正則表達式的更多細節,你能夠參考編寫編譯器的有關資料。

------------------------------------------------------------------------------------------------------------------------------------------------------------
2.1.字符匹配
大多數字符和字母會簡單地匹配它們本身,好比,正則表達式test能夠徹底匹配字符串test(你可使用不區分大小寫模式,那麼這個正則表達式也能夠匹配Test或者TEST;稍後會介紹更多這方面的細節)。


固然這個規則也有例外,有一些字符是特殊的【元字符】,它們並不匹配它們自身。相反的,它們表示將要匹配一些不一樣的東西,或者經過重複、改變意義等影響RE中的其餘部分。本篇文檔大部份內容都致力於討論各類元字符和它們的用法。


這是元字符的完整列表,它們的意義將在隨後討論:

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

咱們先看一下方括號 [ ] .它們指定一個【字符類】,用來存放你但願匹配的字符集合。這些字符能夠單獨列出,一個連續範圍內的字符也能夠用橫槓‘-’鏈接首尾兩個字符指定。好比,[abc]能夠匹配a,b或c,[a-c]也有一樣的效果,後者使用範圍表達式來指定與前者相同的字符集合。若是你只想匹配小寫字母,那麼你的正則表達式爲[a-z]。


須要注意的是,元字符在方括號內不會被激活!好比,[akm$]能夠匹配字符‘a’,‘k’,‘m’或者‘$’,咱們知道‘$’也是一個元字符,可是在方括號內,它就會失去它的特性,只會匹配它自身。


你也能夠匹配未在方括號中列出的字符,這須要在方括號中的第一個字符前面加上‘^’脫字符號,方括號字符集合以外的字符能夠簡單地匹配‘^’符號。好比,[^5]能夠匹配任何不是‘5’的字符。

可能最重要的元字符是反斜槓\。在Python常規語法中,反斜槓後面跟上不一樣的字符表示特殊的序列。在正則表達式中也是同樣,若是反斜槓後面跟着一個元字符,那麼元字符的「特殊功能」將不會被觸發。好比你須要去匹配一個  [ 或者 \ ,你能夠在它們以前加上反斜槓 \ 以去掉它們的特殊語義:\ [ 或者 \\


有一些特殊的、經常使用的序列也以反斜槓開始,好比十進制數字,或者非空白的字符集合。

讓咱們來舉個例子:\w匹配全部字母數字字符,若是正則表達式以字節的形式表示,這至關於字符類[a-zA-Z0-9]。若是正則表達式是一個字符串,\w 會匹配全部在Unicode數據庫中標記的爲字母的字符。你在編譯正則表達式的時候能夠經過提供re.ASCII標誌進一步限制 \w的定義。

下面列舉一些反斜槓加字符構成的特殊序列(並不完整)。
\d:匹配全部十進制數字,至關於字符類[0-9]
\D:匹配全部非數字字符,至關於字符類[^0-9]
\s:匹配全部空白字符(包括製表符、換行符等),至關於字符類[\t\n\r\f\v]
\S:匹配全部非空白字符,至關於字符類[^\t\n\r\f\v]
\w:匹配全部字母數字字符,至關於字符類[a-zA-Z0-9]
\W:匹配全部非字母數字字符,至關於字符類[^a-zA-Z0-9]


這些序列能夠被包含在一個字符類中,好比,[\s,.]是一個字符類,能夠匹配任何空白字符,或者‘,’和‘.’

這部分最後的一個元字符是‘.’,它匹配除了換行符以外的任何字符,若是設置了re.DOTALL標誌,它將匹配包含換行符在內的全部字符。

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

2.2.重複的事情
可以匹配不一樣的字符是正則表達式能夠作的第一件事情,但Python字符串現有的方法卻沒法實現。然而,若是這是正則表達式惟一的優點,那麼它也不會有太大的進步。它的另外一個強大的功能是你能夠指定RE部分被重複的次數。

首先咱們來學習有重複做用的第一個元字符星號 * ,它並不匹配它自身,而是指定它的前一個字符重複0次或者屢次,而不是肯定的多少次。


好比,ca*t能夠匹配ct(有0個a字符)、cat(有1個a字符)、caaat(有3 個a字符)等等。不過受到正則表達式引擎C語言中int類型的限制,‘a’字符的重複次數不能超過2億次,然而咱們日常也用不到這麼大的數據。


正則表達式的重複規則是貪婪的,當重複匹配一個RE時,匹配引擎會盡量多地去匹配,直到不匹配或者到告終尾,匹配引擎就會回退一個字符,而後再嘗試匹配。


咱們經過例子來一步步地讓這個概念更清晰。讓咱們考慮一個正則表達式a[bcd]*b,它要先匹配字符‘a’,而後匹配0個或多個字符類[bcd]中的字符,最後以字符‘b’結尾。如今假如它要匹配字符串‘abcbd’:

步驟 匹配 解釋
1 a 匹配RE的第一個字符a
2 abcbd 引擎儘量遠地匹配[bcd]*,直到該字符串的結尾
3 Failure 引擎嘗試去匹配b,但當前位置已是字符串的末尾了,因此失敗
4 abcb 回退一個字符,因此[bcd]*匹配少一個字符
5 Failure 引擎再次嘗試匹配b,可是當前位置最後一個字符是d,因此失敗
6 abc 再次回退一個字符,因此[bdc]*只匹配bc
7 abcb 再次匹配b,這一次當前位置的字符正好是b,因此匹配成功
RE匹配完成,因此最終,RE匹配的結果是abcb。這個例子證實了上述的討論,正則表達式引擎老是先儘量遠的匹配重複的字符,若是不匹配,他將逐步回退,而後再次嘗試去匹配RE剩餘的部分,直到重複字符的個數爲0,若是這時仍然匹配失敗,引擎就會得出結論:這個字符串不匹配這個RE。


另外一個表示重複的元字符是加號 + ,它指定匹配它前面的字符1次或者屢次。這裏要注意星號 * 和加號 + 的區別,星號 * 匹配0次或者屢次,因此被匹配的內容可能壓根兒就不出現,可是加號 + 要求重複的字符至少出現1次。舉一個簡單的例子,ca+t能夠匹配cat(1個a字符)、caaat(3個a字符),可是它不匹配ct。


還有兩個表示重複的元字符,其中一個就是問號 ? ,它用於指定匹配它前面的字符0次或者1次,你能夠認爲它用於標誌一個可選的字符。好比,home-?brew能夠匹配homebrew或者home-brew。

最靈活的表示重複的限定符應該是{m,n},這裏的m和n都是十進制數字。這表示它前面的字符至少重複m次,最多重複n次。好比,a/{1,3}b能夠匹配a/b,a//b和a///b。可是它不匹配ab,由於ab沒有斜槓,也不匹配a////b,由於它有4個斜槓超過了3個。


你也能夠省略m或者n,在這種狀況下,引擎會假定一個合理的替代值。省略m將默認下限爲0,省略n將默認無上限,即上限無窮大——固然,根據上文提到的,它不能超過2億。(譯者注:還有一種使用方式,{n}指定它前面的字符重複n次)

聰明的讀者可能已經發現了,上文提到的星號 *、加號 +和問號 ?均可以用這個限定符表示。{0,}與星號 * 做用同樣,{1,}與加號 + 做用同樣,{0,1}與問號 ? 做用同樣。然而,在實際應用中,首選星號 * 、加號 + 和問號 ?,由於它們更短,效率更高。