2020年9月12日星期六

59 《零基礎入門學習Python》筆記 第059講:論一隻爬蟲的自我修養7:正則表達式3

《零基礎入門學習Python》筆記  第059講:論一隻爬蟲的自我修養7:正則表達式3

上節課我們介紹了正則表達式的特殊字符中的元字符,正則表達式的特殊字符除了元字符之外呢,還有一種就是通過反斜杠加上一個普通字符組成的特殊符號。我們接下來談談它們的含義。
\序號,這個我們上節課已經講過了,序號就是數字:
①引用序號對應的子組所匹配的字符串,此時序號的範圍是1~99,子組的序號是從1 開始計算。
②如果序號是以0開頭,或者3位數字的長度。那麼不會被用於引用對應的子組,而是用於匹配八進制數字所表示的ASCII碼值對應的字符。
這在上節課已經講過了,我們接下來就講上節課沒有講過的:
\A :這個符號在默認情況下和托字符(^)是一樣的,都是匹配輸入字符串的開始位置。也就是說,要是前面是\A 或者^ 符號,那麼這個字符就必須出現在字符串的開頭,才能算是匹配。有不懂的,可以查看上節課托字符(^)的講解。
\Z:這個符號在默認情況下和美元符號($)是一樣的,都表示匹配輸入字符串的結束位置。
我們上面兩條都說的是默認情況下,但不是說完全一樣的。因為正則表達式還有一個編譯標誌的設置,如果說你設置了一個re.MULTILINE 標誌,那麼托字符(^)也匹配換行符之後的位置,同時,美元符號($)也匹配換行符之前的位置。
但是呢,無論你設不設置這個標誌,這個\A 和\Z 都只能匹配字符串的開頭和結束位置。
像這種匹配位置的字符,我們給它們一個名字,叫做臨框斷言,言外之意就是它們不會匹配任何字符,它們只用於定位一個位置。
\b 也是一個臨框斷言,它是匹配一個單詞的邊界,單詞被定義為Unidcode 的字母數字或下橫線字符。舉個例子:
  1. >>> import re
  2. >>> re.findall(r"\bFishC\b", "FishC.com!FishC_com!(FishC)")
  3. ['FishC', 'FishC']
上面只找到了兩個FishC,你知道它哪一個FishC沒有找到嗎?(事實上是FishC_com 中的FishC),因為下劃線也被認為是單詞字符,不是邊界。點號(.)感嘆號(!)、括號都被認為是單詞邊界。
接下來是\B,其實就是與\b 相反,匹配非單詞邊界。
舉個例子:py\B 會匹配字符串"python"、"py3"或"py2",但不會匹配"py "、"py."或"py!"
\d:① 對於Unicode(str 類型)模式:匹配任何一個數字,包括[0-9] 和其他數字字符;如果開啟了re.ASCII 標誌,就只匹配[0-9]。
② 對於8 位(bytes 類型)模式:匹配[0-9] 中任何一個數字。
\D:與\d 相反,匹配任何非Unicode 的數字;如果開啟了re.ASCII 標誌,則相當於匹配[^0-9]。
\s :①對於Unicode(str類型)模式:匹配Unicode中的空白字符(包括[ \t \n \r \f \v ]以及其他空白字符);如果開啟了re.ASCII標誌,就只匹配[ \t\n\r\f\v]
② 對於8 位(bytes 類型)模式:匹配ASCII 中定義的空白字符,即[ \t\n\r\f\v]
\w:①對於Unicode(str類型)模式:匹配任何Unicode的單詞字符,基本上所有語言的字符都可以匹配當然也包括數字和下橫線;如果開啟了re.ASCII標誌,就只匹配[ a-zA-Z0-9_]
什麼是單詞字符?對於英文(就是ASCII)的話,像“Python”,P y t h o n 這6個字符都是單詞字符,還有數字和下橫線也是。如果是Unicode 的話, Unicode 是全球化的語言,像中文,中文什麼是單詞字符?例如“我愛Python”,其中的 我 愛 這兩個漢字也是單詞字符。
② 對於8 位(bytes 類型)模式:匹配ASCII 中定義的字母數字,即[a-zA-Z0-9_]
舉個例子:
  1. >>> re.findall(r"\w", "我爱Python3 (love_python.com!)")
  2. ['我', '爱', 'P', 'y', 't', 'h', 'o', 'n', '3', 'l', 'o', 'v', 'e', '_', 'p', 'y', 't', 'h', 'o', 'n', 'c', 'o', 'm']
除了空格括號點號感嘆號,其它的漢字、字母、下橫線、數字都是單詞字符。
\W :其實就是與\w 相反, 匹配任何非Unicode 的單詞字符,;如果開啟了re.ASCII 標誌,則相當於[^a-zA-Z0-9_]
最後,正則表達式還支持大部分Python 字符串的轉義符號:\a,\b,\f,\n,\r,\t,\u,\U,\v,\x,\\
注1:\b通常用於匹配一個單詞邊界,只有在字符類中才表示“退格”
注2:\u 和\U 只有在Unicode 模式下才會被識別
注3:八進制轉義(\數字)是有限制的,如果第一個數字是0,或者如果有3 個八進制數字,那麼就被認為是八進制數;其他情況則被認為是子組引用;至於字符串,八進制轉義總是最多只能是3 個數字的長度。
 Python3正則表達式特殊符號及用法(詳細列表)這個表格終於講解完畢了,還是那句話,別死記硬背,查用就行。

接下來講解下一個內容:編譯正則表達式:

什麼情況下需要編譯正則表達式?
如果你需要重複地使用某個正則表表達式,那麼你可以先把該正則表達式編譯成模式對象。

我們使用re.compile()方法來編譯……

re.compile 函數

compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供match() 和search() 這兩個函數使用。
語法格式為:

re.compile(pattern[, flags])

參數:
  • pattern : 一個字符串形式的正則表達式
  • flags : 可選,表示匹配模式,比如忽略大小寫,多行模式等,具體參數為:
    1. re.I  忽略大小寫
    2. re.L  表示特殊字符集\w, \W, \b, \B, \s, \S依賴於當前環境
    3. re.M  多行模式
    4. re.S  即為.並且包括換行符在內的任意字符(.不包括換行符)
    5. re.U  表示特殊字符集\w, \W, \b, \B, \d, \D, \s, \S依賴於Unicode字符屬性數據庫
    6. re.X  為了增加可讀性,忽略空格和#後面的註釋

      關於這6個編譯標誌的詳解可以查看  Python3如何優雅地使用正則表達式(詳解三)

  1. >>> p = re.compile(r"[A-Z]")
  2. >>> type(p)
  3. <class '_sre.SRE_Pattern'>
我們把正則表達式[AZ] 進行編譯,賦值給一個變量p,這個變量p 就是一個模式對象。
我們可以直接使用p 進行search() 方法和findall() 方法 的使用:
  1. >>> p.search("I love Python")
  2. <_sre.SRE_Match object; span=(0, 1), match='I'>
  3. >>> p.findall("I love Python")
  4. ['I', 'P']
有些朋友可能會問,你是使用模塊級別的方法效率比較高,還是說使用編譯後的方法效率比較高,其實這個沒有一定的定論,因為兩種的優化差不多。這裡,如果你至少需要使用一次正則表達式,你直接使用模塊級別的方法就可以了,但是呢,如果你下面要多次使用這個正則表達式,你就可以先對其進行編譯,再使用,這樣更方便。我們以方便為主,既然學習Python,就不要多考慮效率的問題了,能優化的,Python的設計者都已經優化得差不多了。

接下來我們來談談這個編譯標誌

我們在  Python3如何優雅地使用正則表達式(詳解三)裡有仔細的給大家列舉出來。
編譯標誌讓你可以修改正則表達式的工作方式。在re 模塊下,編譯標誌均有兩個名字:完整名和簡寫。
我們需要提一點的是 VERBOSE(簡寫X)這個標誌,使用re.VERBOSE(或者re.X)在某些時候能給我們帶來很多好處。
因為呢,稍微一個中等複雜度的正則表達式,你就會把它寫成人模狗樣,非常非常的複雜,為什麼呢?因為我們上節課已經說過了,正則表達式裡你不能隨便加空格,因為空格它會被認為是其中的一個匹配元素,你不能加空格,不能加Tab 鍵,不能使用三重引號換行,所以呢,你寫出來的東西就會看起來很難理解。但是如果你開啟了 VERBOSE,它就是支持空格,支持Tab鍵,支持換行,也支持註釋的。

0 留言:

發佈留言