Python正则表达式之编译正则表达式(2)
文章目錄
- 聲明
- 編譯正則表達式
- 麻煩的反斜杠
- 實現匹配
- `match()`
- `search()`
- `findall()`
- `finditer()`
聲明
Python 通過 re 模塊為正則表達式引擎提供一個接口,同時允許你將正則表達式編譯成模式對象,并用它們來進行匹配。
注意:
re 模塊是使用 C 語言編寫,所以效率比你用普通的字符串方法要高得多;將正則表達式進行編譯(compile)也是為了進一步提高效率;后邊我們會經常提到“模式”,指的就是正則表達式被編譯成的模式對象。
編譯正則表達式
正則表達式被編譯為模式對象,該對象擁有各種方法供你操作字符串,如查找模式匹配或者執行字符串替換。
import re p = re.compile('ab*')
re.compile() 也可以接受 flags 參數,用于開啟各種特殊功能和語法變化,
正則表達式作為一個字符串參數傳給 re.compile()。由于正則表達式并不是 Python 的核心部分,因此沒有為它提供特殊的語法支持,所以正則表達式只能以字符串的形式表示。(有些應用根本就不需要使用到正則表達式,所以 Python 社區的小伙伴們認為沒有必要將其納入 Python 的核心。)相反,re 模塊僅僅是作為 C 的擴展模塊包含在 Python 中,就像 socket 模塊和 zlib 模塊。
麻煩的反斜杠
正則表達式使用 '\' 字符來使得一些普通的字符擁有特殊的能力(例如 \d 表示匹配任何十進制數字),或者剝奪一些特殊字符的能力(例如 \[ 表示匹配左方括號 '[')。這會跟 Python 字符串中實現相同功能的字符發生沖突。
假如你需要在 LaTeX 文件中使用正則表達式匹配字符串 '\section'。因為反斜杠作為需要匹配的特殊字符,所以你需要再它前邊加多一個反斜杠來剝奪它的特殊功能。所以我們會把正則表達式的字符寫成 '\\section'
Python 在字符串中同樣使用反斜杠來表示特殊意義。因此,如果我們想將 '\\section' 完整地傳給 re.compile(),我們需要再次添加兩個反斜杠…
| \section | 需要匹配的字符串 |
| \\section | 正則表達式使用 '\\' 表示匹配字符 '\' |
| "\\\\section" | 不巧,Python 字符串也使用 '\\' 表示字符 '\' |
簡而言之,為了匹配反斜杠這個字符,我們需要在字符串中使用四個反斜杠才行。所以,在正則表達式中頻繁地使用反斜杠,會造成反斜杠風暴,進而導致你的字符串極其難懂。
解決方法是使用 Python 的原始字符串來表示正則表達式(就是在字符串前邊加上 r,大家還記得吧…):
| "ab*" | r"ab*" |
| "\\\\section" | r"\\section" |
| "\\w+\\s+\\1" | r"\w+\s+\1" |
建議使用原始字符串來表達正則表達式。
實現匹配
當你將正則表達式編譯之后,你就得到一個模式對象。那你拿他可以用來做什么呢?模式對象擁有很多方法和屬性,我們下邊列舉最重要的幾個來講:
| match() | 判斷一個正則表達式是否從開始處匹配一個字符串 |
| search() | 遍歷字符串,找到正則表達式匹配的第一個位置 |
| findall() | 遍歷字符串,找到正則表達式匹配的所有位置,并以列表的形式返回 |
| finditer() | 遍歷字符串,找到正則表達式匹配的所有位置,并以迭代器的形式返回 |
如果沒有找到任何匹配的話,match() 和 search() 會返回 None;如果匹配成功,則會返回一個匹配對象(match object),包含所有匹配的信息:例如從哪兒開始,到哪兒結束,匹配的子字符串等等
match()
接下來我們一步步講解:
>>> import re >>> p = re.compile('[a-z]+') >>> p re.compile('[a-z]+')實現截圖:
現在,你可以嘗試使用正則表達式 [a-z]+ 去匹配各種字符串。
例如:
實現截圖:
因為 + 表示匹配一次或者多次,所以空字符串不能被匹配。因此,match() 返回 None。
我們再嘗試一個可以匹配的字符串:
>>> m = p.match('fish') >>> m <_sre.SRE_Match object; span=(0, 4), match='fish'>實現截圖:
在這個例子中,match() 返回一個匹配對象,我們將其存放在變量 m 中,以便日后使用。
接下來讓我們來看看匹配對象里邊有哪些信息吧。匹配對象包含了很多方法和屬性,以下幾個是最重要的:
| group() | 返回匹配的字符串 |
| start() | 返回匹配的開始位置 |
| end() | 返回匹配的結束位置 |
| span() | 返回一個元組表示匹配位置(開始,結束) |
實現截圖:
由于 match() 只檢查正則表達式是否在字符串的起始位置匹配,所以 start() 總是返回 0。
search()
然而,search() 方法可就不一樣咯:
>>> print(p.match('^_^fish')) None >>> m = p.search('^_^fish') >>> print(m) <_sre.SRE_Match object; span=(3, 7), match='fish'> >>> m.group() 'fish' >>> m.span() (3, 7) >>> m=p.search('^_^f123i54sh') >>> m <re.Match object; span=(3, 4), match='f'>實現截圖:
在實際應用中,最常用的方式是將匹配對象存放在一個局部變量中,并檢查其返回值是否為 None。
形式通常如下:
p = re.compile( ... ) m = p.match( 'string goes here' ) if m:print('Match found: ', m.group()) else:print('No match')有兩個方法可以返回所有的匹配結果,一個是 findall(),另一個是 finditer()。
findall()
findall() 返回的是一個列表:
>>> p = re.compile('\d+') >>> p.findall('3只小狗,15條腿,多出的3條在哪里?') ['3', '15', '3']實現截圖:
finditer()
findall() 需要在返回前先創建一個列表,而 finditer() 則是將匹配對象作為一個迭代器返回:
>>> iterator = p.finditer('3只小狗,15條腿,多出的3條在哪里?') >>> iterator <callable_iterator object at 0x00000212CE96ADC8> >>> for match in iterator:print(match.span())(0, 1) (5, 7) (13, 14)實現截圖:
如果列表很大,那么返回迭代器的效率要高很多
總結
以上是生活随笔為你收集整理的Python正则表达式之编译正则表达式(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python3 正则表达式特殊符号及用法
- 下一篇: Request模块基本常识