Python正则表达式之额外补充(7)
文章目錄
- 使用字符串方法
- match() VS search()
- 貪婪 VS 非貪婪
- 使用 `re.VERBOSE`
本篇我們將指出一些最常見的錯誤。
使用字符串方法
有時使用 re 模塊是個錯誤!如果你匹配一個固定的字符串或者單個字符類,并且你沒有使用 re 的任何標志(像 IGNORECASE 標志),那么就沒有必要使用正則表達式了。字符串有一些方法是對固定字符串進行操作的,并且它們通常比較快。因為它們都是獨立優(yōu)化的 C 語言小循環(huán),目的是在簡單的情況下代替功能更加強大、更具通用性的正則表達式引擎。
舉個例子,例如你想把字符串中所有的 dead 替換成 word,你會想到使用正則表達式的 re.sub() 方法來實現(xiàn),但這么簡單的替換,還是考慮直接使用字符串的 replace() 方法吧。但有一點你需要注意,就是 replace() 會在單詞里邊進行替換,像 swordfish 會變成 sdeedfish,這顯然不是你想要的!replace() 沒辦法識別單詞的邊界,因此你才來考慮使用正則表達式。只需要將 RE 的模式寫成 \bword\b 即可勝任此任務。
另一個常見的情況是從一個字符串中刪除單個字符或者用另一個字符替代它。你也許會想到用 re.sub('\n', ' ', S) 這樣的正則表達式來實現(xiàn),但其實字符的 translate() 方法完全能夠勝任這個任務,并且比任何正則表達式操作起來更快些。
簡而言之,在使用 re 模塊之前,先考慮一下你的問題是否可以用更快速、簡單的字符串自帶方法來解決。
match() VS search()
match() 函數(shù)只會檢查 RE 是否在字符串的開始處匹配,而 search() 會遍歷整個字符串搜索匹配的內(nèi)容。記住這一區(qū)別很重要。再次強調(diào)一下,match() 只會報告一次成功的匹配,并且匹配的位置必須是從字符串的第一個字符開始:
>>> print(re.match('super', 'superstition').span()) (0, 5) >>> print(re.match('super', 'insuperable')) None另一方面,search() 函數(shù)將遍歷整個字符串,并報告它找到的第一個匹配:
>>> print(re.search('super', 'superstition').span()) (0, 5) >>> print(re.search('super', 'insuperable').span()) (2, 7)有時候你可能會耍點小聰明,使用 re.match() 然后在 RE 的前邊加上 .*。但盡量不要這么做,最好采用 re.search() 代替。正則表達式編譯器會對 REs 做一些分析,以便可以在搜索匹配時提高速度。一般分析會先找到匹配的第一個字符是什么。舉個例子,模式 Crow 必須從字符 'C' 開始匹配,那么匹配引擎分析后會快速遍歷字符串,然后在 'C' 被找到之后才開始全部匹配。
按照上面的分析,你添加一個 .* 會導致這個優(yōu)化失敗,這就需要從頭到尾掃描一遍,然后再回溯匹配 RE 剩余的部分。所以,請使用 re.search() 代替。
貪婪 VS 非貪婪
當重復一個正則表達式時,如果使用 a*,那么結果是盡可能多地去匹配。當你嘗試匹配一對對稱的定界符,例如 HTML 標志中的尖括號,默認的貪婪模式會使得你很困擾。
我們來看下例子:
>>> s = '<html><head><title>Title</title>' >>> len(s) 32 >>> print(re.match('<.*>', s).span()) (0, 32) >>> print(re.match('<.*>', s).group()) <html><head><title>Title</title>RE 匹配在 <html> 的 < 后,.* 消耗掉字符串的剩余部分。由于正則表達式默認是貪婪的原因,RE 必須從字符串的尾部一個字符一個字符地回溯,直到找到匹配的 >。大家看到,按照這種方法,最后找到匹配內(nèi)容竟是 <html> 的 < 開始,到 </title> 的 > 結束。顯然這不是你想要的結果。
在這種情況下,解決方案是使用非貪婪的限定符 *?、+?、?? 或 {m,n}?,盡可能地匹配小的文本。
>>> print(re.match('<.*?>', s).group()) <html>在上邊的例子中,> 在第一個 < 被匹配后立刻嘗試匹配,如果失敗,匹配引擎前進一步,嘗試下一個字符,直到第一次匹配 >,這樣就得到了我們想要的結果。
注意,使用正則表達式分析 HTML 和 XML 是很痛苦的。當你編寫一個正則表達式去處理所有可能的情況時,你會發(fā)現(xiàn) HTML 和 XML 總會打破你的“規(guī)則”,這讓你很頭疼…像這樣的話,建議使用 HTML 和 XML 解析器來處理更合適。
使用 re.VERBOSE
現(xiàn)在你應該意識到了,**正則表達式的表示非常緊湊。這也帶來了一個問題,就是不好閱讀。**中等復雜的正則表達式可能包含許多反斜杠、圓括號和元字符,以至于難以讀懂。
在這些 REs 中,當編譯正則表達式時指定 re.VERBOSE 標志是非常有幫助的。因為它允許你可以編輯正則表達式的格式,使之更清楚。
re.VERBOSE 標志有幾個作用。在正則表達式中不在字符類中的空白字符將被忽略。這就意味著像 I love FishC 這樣的表達式和可讀性較差的 IloveFishC 相同。但 [a b] 將匹配字符 ‘a(chǎn)’、‘b’ 或 ’ ';另外,你也可以把注釋放到 RE 中,注釋是從 # 開始到下一行。當使用三引號字符串時,會使得 REs 的格式更整潔:
pat = re.compile(r"""\s* # Skip leading whitespace(?P<header>[^:]+) # Header name\s* : # Whitespace, and a colon(?P<value>.*?) # The header's value -- *? used to# lose the following trailing whitespace\s*$ # Trailing whitespace to end-of-line """, re.VERBOSE)同樣的內(nèi)容,下邊這個要難讀得多:
pat = re.compile(r"\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$") 《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Python正则表达式之额外补充(7)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL语法详解
- 下一篇: websocket python爬虫_p