<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python正則表達(dá)式,這一篇就夠了!

          共 6043字,需瀏覽 13分鐘

           ·

          2021-01-06 10:29

          之前我們講解了 正則表達(dá)式 的起源、發(fā)展、流派、語法、引擎、優(yōu)化等相關(guān)知識,今天我們主要來學(xué)習(xí)一下 正則表達(dá)式在 Python語言 中的應(yīng)用
          大多數(shù)編程語言的正則表達(dá)式設(shè)計都師從Perl,所以語法基本相似,不同的是每種語言都有自己的函數(shù)去支持正則,今天我們就來學(xué)習(xí) Python中關(guān)于 正則表達(dá)式的函數(shù)。
          re模塊主要定義了9個常量、12個函數(shù)、1個異常,每個常量和函數(shù)豬哥都會通過實際代碼案例講解,讓大家能更直觀的了解其作用!
          注:為避免出現(xiàn)代碼格式錯亂,豬哥盡量使用代碼截圖演示哦。


          一、re模塊簡介

          聊到Python正則表達(dá)式的支持,首先肯定會想到re庫,這是一個Python處理文本的標(biāo)準(zhǔn)庫
          標(biāo)準(zhǔn)庫的意思表示這是一個Python內(nèi)置模塊,不需要額外下載,目前Python內(nèi)置模塊大概有300個。可以在這里查看Python所有的內(nèi)置模塊:https://docs.python.org/3/py-modindex.html#cap-r


          因為re是內(nèi)置模塊,所以不需要再下載,使用時直接引入即可:
          import re


          re模塊官方文檔:https://docs.python.org/zh-cn/3.8/library/re.html
          re模塊庫源碼:https://github.com/python/cpython/blob/3.8/Lib/re.py


          二、re模塊常量

          常量即表示不可更改的變量,一般用于做標(biāo)記。
          re模塊中有9個常量,常量的值都是int類型!
          上圖我們可以看到,所有的常量都是在RegexFlag枚舉類來實現(xiàn),這是在Python 3.6做的改版。在Python 3.6以前版本是直接將常量寫在re.py中,使用枚舉的好處就是方便管理和使用!
          下面我們來快速學(xué)習(xí)這些常量的作用及如何使用他們,按常用度排序!

          1. IGNORECASE

          語法: re.IGNORECASE 或簡寫為 re.I
          作用: 進行忽略大小寫匹配。
          代碼案例:
          在默認(rèn)匹配模式下大寫字母B無法匹配小寫字母b,而在 忽略大小寫 模式下是可以的。

          2. ASCII

          語法: re.ASCII 或簡寫為 re.A
          作用: 顧名思義,ASCII表示ASCII碼的意思,讓 \w, \W, \b, \B, \d, \D, \s\S 只匹配ASCII,而不是Unicode。
          代碼案例:

          在默認(rèn)匹配模式下\w+匹配到了所有字符串,而在ASCII模式下,只匹配到了a、b、c(ASCII編碼支持的字符)。
          注意:這只對字符串匹配模式有效,對字節(jié)匹配模式無效。

          3. DOTALL

          語法: re.DOTALL 或簡寫為 re.S
          作用: DOT表示.,ALL表示所有,連起來就是.匹配所有,包括換行符\n默認(rèn)模式下.是不能匹配行符\n
          代碼案例:
          在默認(rèn)匹配模式下.并沒有匹配換行符\n,而是將字符串分開匹配;而在re.DOTALL模式下,換行符\n與字符串一起被匹配到。
          注意:默認(rèn)匹配模式下.并不會匹配換行符\n

          4. MULTILINE

          語法: re.MULTILINE 或簡寫為 re.M
          作用:多行模式,當(dāng)某字符串中有換行符\n,默認(rèn)模式下是不支持換行符特性的,比如:行開頭 和 行結(jié)尾,而多行模式下是支持匹配行開頭的。
          代碼案例:
          正則表達(dá)式中^表示匹配行的開頭,默認(rèn)模式下它只能匹配字符串的開頭;而在多行模式下,它還可以匹配 換行符\n后面的字符。
          注意:正則語法中^匹配行開頭、\A匹配字符串開頭,單行模式下它兩效果一致,多行模式下\A不能識別\n

          5. VERBOSE

          語法:re.VERBOSE 或簡寫為 re.X
          作用:詳細(xì)模式,可以在正則表達(dá)式中加注解!
          代碼案例:

          默認(rèn)模式下并不能識別正則表達(dá)式中的注釋,而詳細(xì)模式是可以識別的。
          當(dāng)一個正則表達(dá)式十分復(fù)雜的時候,詳細(xì)模式或許能為你提供另一種注釋方式,但它不應(yīng)該成為炫技的手段,建議謹(jǐn)慎考慮后使用!

          6.LOCALE

          語法: re.LOCALE 或簡寫為 re.L
          作用: 由當(dāng)前語言區(qū)域決定 \w, \W, \b, \B 和大小寫敏感匹配,這個標(biāo)記只能對byte樣式有效。這個標(biāo)記官方已經(jīng)不推薦使用,因為語言區(qū)域機制很不可靠,它一次只能處理一個 “習(xí)慣”,而且只對8位字節(jié)有效。
          注意: 由于這個標(biāo)記官方已經(jīng)不推薦使用,而且豬哥也沒使用過,所以就不給出實際的案例!

          7.UNICODE

          語法: re.UNICODE 或簡寫為 re.U
          作用: 與 ASCII 模式類似,匹配unicode編碼支持的字符,但是 Python 3 默認(rèn)字符串已經(jīng)是Unicode,所以有點冗余。

          8. DEBUG

          語法: re.DEBUG
          作用: 顯示編譯時的debug信息。
          代碼案例:
          雖然debug模式下確實會打印編譯信息,但豬哥并不理解這是什么語言 以及表達(dá)的含義,希望了解的朋友能不吝賜教。

          9.TEMPLATE

          語法: re.TEMPLATE ?或簡寫為 re.T
          作用: 豬哥也沒搞懂TEMPLATE的具體用處,源碼注釋中寫著:disable backtracking(禁用回溯),有了解的同學(xué)可以留言告知!

          10. 常量總結(jié)

          1. 9個常量中,前5個(IGNORECASE、ASCII、DOTALL、MULTILINE、VERBOSE)有用處,兩個(LOCALE、UNICODE)官方不建議使用、兩個(TEMPLATE、DEBUG)試驗性功能,不能依賴。

          2. 常量在re常用函數(shù)中都可以使用,查看源碼可得知。

          3. 常量可疊加使用,因為常量值都是2的冪次方值,所以是可以疊加使用的,疊加時請使用 | 符號,請勿使用+ 符號!


          最后來一張思維導(dǎo)圖總結(jié)一下re模塊中的常量吧,需要高清圖或者xmind文件的同學(xué)可在文章末尾獲取。


          三、re模塊函數(shù)

          re模塊有12個函數(shù),豬哥將以功能分類來講解;這樣更具有比較性,同時也方便記憶。

          1.查找一個匹配項

          查找并返回一個匹配項的函數(shù)有3個:search、match、fullmatch,他們的區(qū)別分別是:
          1. search 查找任意位置的匹配項

          2. match 必須從字符串開頭匹配

          3. fullmatch 整個字符串與正則完全匹配


          我們再來根據(jù)實際的代碼案例比較:

          案例1:

          案例1中search函數(shù)是在字符串中任意位置匹配,只要有符合正則表達(dá)式的字符串就匹配成功,其實有兩個匹配項,但search函數(shù)值返回一個。
          match函數(shù)是要從頭開始匹配,而字符串開頭多了個字母a,所以無法匹配,fullmatch函數(shù)需要完全相同,故也不匹配!
          案例2:
          案例2刪除了text最開頭的字母a,這樣match函數(shù)就可以匹配啦,而fullmatch函數(shù)依然不能完全匹配!
          案例3:

          案例3中,我們只留下一段文字,并且與正則表達(dá)式一致;這時fullmatch函數(shù)終于可以匹配了。
          完整案例:

          注意:查找 一個匹配項 返回的都是一個匹配對象(Match)。

          2.查找多個匹配項

          講完查找一項,現(xiàn)在來看看查找多項吧,查找多項函數(shù)主要有:findall函數(shù)finditer函數(shù)
          1. findall 從字符串任意位置查找,返回一個列表

          2. finditer:從字符串任意位置查找,返回一個迭代器


          兩個方法基本類似,只不過一個是返回列表,一個是返回迭代器。我們知道列表是一次性生成在內(nèi)存中,而迭代器是需要使用時一點一點生成出來的,內(nèi)存使用更優(yōu)。

          如果可能存在大量的匹配項的話,建議使用finditer函數(shù),一般情況使用findall函數(shù)基本沒啥影響。

          3.分割

          re.split(pattern, string, maxsplit=0, flags=0) 函數(shù):用 pattern 分開 string , maxsplit表示最多進行分割次數(shù), flags表示模式,就是上面我們講解的常量!

          注意:str模塊也有一個 split函數(shù) ,那這兩個函數(shù)該怎么選呢?
          str.split函數(shù)功能簡單,不支持正則分割,而re.split支持正則。
          關(guān)于二者的速度如何? 豬哥實際測試了一下,在相同數(shù)據(jù)量的情況下使用re.split函數(shù)與str.split函數(shù)執(zhí)行次數(shù) ?與 執(zhí)行時間 對比圖:

          通過上圖對比發(fā)現(xiàn),1000次循環(huán)以內(nèi)str.split函數(shù)更快,而循環(huán)次數(shù)1000次以上后re.split函數(shù)明顯更快,而且次數(shù)越多差距越大!
          所以結(jié)論是:在 不需要正則支持 且 數(shù)據(jù)量和數(shù)次不多 的情況下使用str.split函數(shù)更合適,反之則使用re.split函數(shù)
          注:具體執(zhí)行時間與測試數(shù)據(jù)有關(guān)!

          4.替換

          替換主要有sub函數(shù)subn函數(shù),他們功能類似!
          先來看看sub函數(shù)的用法:
          re.sub(pattern, repl, string, count=0, flags=0) 函數(shù)參數(shù)講解:repl替換掉string中被pattern匹配的字符, count表示最大替換次數(shù),flags表示正則表達(dá)式的常量。
          值得注意的是:sub函數(shù)中的入?yún)ⅲ?strong>repl替換內(nèi)容既可以是字符串,也可以是一個函數(shù)哦! 如果repl為函數(shù)時,只能有一個入?yún)ⅲ篗atch匹配對象。
          re.subn(pattern, repl, string, count=0, flags=0) 函數(shù)與 re.sub函數(shù) 功能一致,只不過返回一個元組 (字符串, 替換次數(shù))。

          5.編譯正則對象

          compile函數(shù)template函數(shù) 將正則表達(dá)式的樣式編譯為一個 正則表達(dá)式對象 (正則對象Pattern),這個對象與re模塊有同樣的正則函數(shù)(后面我們會講解Pattern正則對象)。

          template函數(shù)compile函數(shù) 類似,只不過是增加了我們之前說的re.TEMPLATE 模式,我們可以看看源碼。

          6.其他

          re.escape(pattern) 可以轉(zhuǎn)義正則表達(dá)式中具有特殊含義的字符,比如:. 或者 * ,舉個實際的案例:

          re.escape(pattern) 看似非常好用省去了我們自己加轉(zhuǎn)義,但是使用它很容易出現(xiàn)轉(zhuǎn)義錯誤的問題,所以并不建議使用它轉(zhuǎn)義,而建議大家自己手動轉(zhuǎn)義
          re.purge() 函數(shù)作用就是清除 正則表達(dá)式緩存,具體有什么緩存呢?我們來看看源碼就知道它背地里干了 什么:

          看方法大概是清除緩存吧,我們再來看看具體的案例:

          豬哥在兩個案例之間使用了re.purge() 函數(shù)清除緩存,然后分別比較前后案例源碼里面的緩存,看看是否有變化!

          7.總結(jié)

          同樣,最后來一張思維導(dǎo)圖總結(jié)一下re模塊中的函數(shù)吧,需要高清圖或者xmind文件的同學(xué)可在末尾獲取。


          四、re模塊異常

          re模塊還包含了一個正則表達(dá)式的編譯錯誤,當(dāng)我們給出的正則表達(dá)式是一個無效的表達(dá)式(就是表達(dá)式本身有問題)時,就會raise一個異常!
          我們來看看具體的案例吧:

          上圖案例中我們可以看到,在編寫正則表達(dá)式中我們多寫了一個后括號,這導(dǎo)致執(zhí)行結(jié)果報錯;而且是在其他所有案例執(zhí)行之前,所以說明是在正則表達(dá)式編譯時期就報錯了。
          注意:這個異常一定是 正則表達(dá)式 本身是無效的,與要匹配的字符串無關(guān)!


          五、正則對象Pattern

          關(guān)于re模塊的常量、函數(shù)、異常我們都講解完畢,但是完全有必要再講講正則對象Pattern

          1. ?與re模塊 函數(shù)一致

          re模塊的函數(shù)中有一個重要的函數(shù) compile函數(shù) ,這個函數(shù)可以預(yù)編譯返回一個正則對象,此正則對象擁有與re模塊相同的函數(shù),我們來看看Pattern類的源碼。

          既然是一致的,那到底該用re模塊 還是 正則對象Pattern
          而且,有些同學(xué)可能看過re模塊的源碼,你會發(fā)現(xiàn)其實compile函數(shù) 與 其他 re函數(shù)(search、split、sub等等) 內(nèi)部調(diào)用的是同一個函數(shù),最終還是調(diào)用正則對象的函數(shù)!

          也就是說下面 兩種代碼寫法底層實現(xiàn) 其實是一致的:
          # re函數(shù)re.search(pattern, text)
          # 正則對象函數(shù)compile = re.compile(pattern)compile.search(text)

          那還有必要使用compile函數(shù) 得到正則對象再去調(diào)用 search函數(shù) 嗎?直接調(diào)用re.search 是不是就可以?

          2. 官方文檔怎么說

          關(guān)于到底該用re模塊 還是 正則對象Pattern ,官方文檔是否有說明呢?

          官方文檔推薦:在多次使用某個正則表達(dá)式時推薦使用正則對象Pattern 以增加復(fù)用性,因為通過 re.compile(pattern) 編譯后的模塊級函數(shù)會被緩存!

          3. 實際測試又如何?

          上面官方文檔推薦我們在 多次使用某個正則表達(dá)式時使用正則對象,那實際情況真的是這樣的嗎?
          我們再實測一下吧

          豬哥編寫了兩個函數(shù),一個使用re.search函數(shù) 另一個使用 compile.search函數(shù) ,分別(不同時)循環(huán)執(zhí)行count次(count從1-1萬),比較兩者的耗時!
          得出的結(jié)果豬哥繪制成折線圖:

          得出的結(jié)論是:100次循環(huán)以內(nèi)兩者的速度基本一致,當(dāng)超出100次后,使用 正則對象Pattern 的函數(shù) 耗時明顯更短,所以比re模塊 要快!
          通過實際測試得知:Python 官方文檔推薦 ?多次使用某個正則表達(dá)式時使用正則對象函數(shù) 基本屬實


          六、注意事項


          Python 正則表達(dá)式知識基本講解完畢,最后稍微給大家提一提需要注意的點。

          1.字節(jié)串 與 字符串

          模式和被搜索的字符串既可以是 Unicode 字符串 (str) ,也可以是8位字節(jié)串 (bytes)。但是,Unicode 字符串與8位字節(jié)串不能混用!

          2.r 的作用

          正則表達(dá)式使用反斜杠(’\’)來表示特殊形式,或者把特殊字符轉(zhuǎn)義成普通字符。
          而反斜杠在普通的 Python 字符串里也有相同的作用,所以就產(chǎn)生了沖突。
          解決辦法是對于正則表達(dá)式樣式使用 Python 的原始字符串表示法;在帶有 ‘r’ 前綴的字符串字面值中,反斜杠不必做任何特殊處理。

          3.正則查找函數(shù) 返回匹配對象

          查找一個匹配項(search、match、fullmatch)的函數(shù)返回值都是一個 匹配對象Match ,需要通過match.group() 獲取匹配值,這個很容易忘記。

          另外還需要注意:match.group()match.groups() 函數(shù)的差別

          4.重復(fù)使用某個正則

          如果要重復(fù)使用某個正則表達(dá)式,推薦先使用 re.compile(pattern)函數(shù) 返回一個正則對象,然后復(fù)用這個正則對象,這樣會更快!

          5.Python 正則面試

          筆試可能會遇到需要使用Python正則表達(dá)式,不過不會太難的,大家只要記住那幾個方法的區(qū)別,會正確使用,基本問題不大。

          最后感謝大家閱讀,希望大家能學(xué)有所成~

          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  四季AV一区二区凹凸懂色 | 日本一级A片色情一区二区 | 特色特黄网址 | 亚洲免费操逼视频 | 欧美精品射精 |