預編譯
import re re1 = re.compile(r"元字符 組成的正則規則") # 元字符下面會說 re1.方法() # 方法下邊也會說元字符:
表示普通字符: . # 除了 外 都可以匹配的到 d # 只匹配 純數字 0-9 D # 和 d相反, 除了數字全都匹配 s # 只匹配空格 S # 和 s相反,除了空格,全都匹配 # 我喜歡用 [sS]*? 匹配所有 w # 只匹配 純數字 或 大小寫字母 或 下劃線 W # 與 w 恰好相反, 除了 純數字、大小寫字母、下劃線 全都匹配 [] # [abcde] 只要包含這個列表的字符,都可以匹配的到。但默認只取一個, 簡寫 [a-e] eg: re.compile(r"[e-h]").match("hello python ").group(0) >>> h 此外: [^abcde] 或 [^a-e] 表示 "排除",意思就是 除了abcde全匹配 匹配表示邊界的: ^ # 匹配 起始 位置,受 re.M 影響 #注意:不要和 [^123] 除123之外搞混 eg: import re r1 = re.compile(r"^d+") print(r1.search("456hello123").group()) >>> 456 $ # 匹配 結尾 位置,受 re.M 影響 eg: import re s = """ 123abc456 678abc789 """ r1 = re.compile(r"d+$",re.M) # 注意這里加入了re.M print(r1.findall(s)) >>> ["456", "789"] # 這是寫了re.M,就意味著 每一行都給你多帶帶按照規則處理 >>> ["789"] # 如果沒寫re.M, 那么就按照整體,去最后一行的尾部 注: 其實re.M的本質是 是根據 ,進行 斷行,斷行后對每一行按照規則多帶帶處理 : # 匹配 單詞的 邊界(除了 數字、中英字母、下劃線 的 所有符號) eg: import re s = "你好啊----好個P" r1 = re.compile(r"好") print(r1.findall(s)) >>> 好 # 解釋:這個‘好’是,后面 的那個。因為后面的 ’好‘ 字 左邊是符號,而非單詞字符 B: # 匹配 單詞 非 邊界(包括 數字、中英字母、下劃線) eg: import re s = "你好啊----好個P" r1 = re.compile(r"好") print(r1.findall(s)) >>> 好 # 解釋:這個‘好’是,前面 的那個。因為前面的 ’好‘ 字 左邊是中文字符。屬于非邊界 # 所以就匹配上了 再次總結: 與 B: : 匹配邊界字符。邊界字符:(除了 數字、字母、漢字、下劃線的所有符號) B: 匹配非邊界字符。非邊界字符:(數字、字母、漢字、下劃線) 匹配表示數量的: * : 0次 或 多次 eg: 你* + : 1次 或 多次 eg: 你+ ? : 0次 或 一次 eg: 你? {m} : 出現m次 eg: 你{3} {m,} : 至少 出現m次 eg: 你{3,} # 涉及到貪婪模式,不深的不要用 {m,n}: m次 到 n次 之間任意一次就行 eg: 你{3,6} 表示分組: | : 相當于或運算符, 兩邊寫的是 正則表達式, 優先選擇左邊的 () : 括起來里面的內容,就變成了分組。 可以用 .group(1)提取,如果有更多那就 group(2).. (?P匹配模式) : 在上面分組的基礎上 起別名 (?P=name) : 根據分組的別名來使用分組 eg: s = " 你好
" r1 = re.compile(r"<(?Pw+)>(w+)(?P=name1)>").match(s).group(2) print(r1) >>> 你好 數字 :提取的分組可以在 同一個正則中 復用 eg: s = " 你好
" r1 = re.compile(r"<(w+)>(w+)1>") # 1 代表復用第一個分組 print(r1.match(s).group(2)) # 2代表提取第二個分組 >>> 你好
re.M # 多行匹配, 影響 ^ 和 $,上面講 ^ 與 $已經詳解了。 re.I # 忽略大小寫 eg: s = "aAbB" r1 = re.compile(r"aabb", re.I).match(s).group() print(r1) >>> aAbB re.S # 提升 . 的權限, 讓 . 可以 匹配到換行符 s = """ hello python """ r1 = re.compile(r".*", re.S).match(s).group() # 注意這里 re.S print(r1) >>> hello python 注意:如果不寫 re.S 那么 .* 只能匹配到第一行的空字符串,因為遇到第一個空行的 就停止了 re.X # 可以給正則分行寫,并可以加注釋, eg: import re title = "1好2你3" r1 = re.compile(r""" 1 # 注釋1 看這兩行 好 # 注釋2 看這兩行,1 和 好 沒有加逗號。但是他們屬于整體的規則,你可以加注釋 """, re.X) # 把正則可以分行寫, 用了re.X后,分行的正則會被看作為一行 result = r1.match(title).group() print(result) # 輸出結果: 1好貪婪模式 與 非貪婪模式
個人理解: 貪婪模式:(Python默認使用的就是 貪婪模式) 你想匹配 一個句子中的 一個單詞, 但是你寫的規則恰好可以 滿足 匹配所有單詞。 那么它就會 貪婪的 把所有單詞 全部 都給你匹配出來。 (貪) 使用方法: * 或 + 非貪婪模式: 即使你把規則寫的很好,并且能把所有字符串都匹配到, 但是如果你加上了 非貪婪模式。 在滿足規則條件的前提下,只匹配一個. 使用方法: *? 或 +? eg1:基于search的貪婪模式(match同此) 我們先回憶一下:search()方法的 最核心思想就是:從前往后搜,搜到一個滿足的就直接返回。 OK,繼續。 貪婪:(默認): import re r1 = re.compile(r"d+") print(r1.search("你好333你好333你好").group()) >>> 333 # 滿足規則后 盡可能貪, 所以第一串連著的 "333" 搜到了就直接返回了 非貪婪(就多了個問號 ? ): import re r1 = re.compile(r"d+?") print(r1.search("你好333你好333你好").group()) >>> 3 # 嗯,你的規則就是 至少一個數字,搜到了一個就可以返回了,干得漂亮。 eg2: 基于findall的貪婪模式(如果你findall與規則,理解的不透徹,這個會有點繞的,前方高能) 先回憶一下:findall()方法的 最核心思想就是:拿著 定死的 規則,把所有滿足規則的都提出來 OK,繼續。 貪婪(默認): import re r1 = re.compile(r"d+") print(r1.findall("你好333你好333你好")) >>> ["333", "333"] 解釋: 規則是匹配至少一位數字。 但是 貪婪模式 提醒了 規則:“你的任務是給我盡可能的 多匹配數字” findall 拿著 被貪婪化的 規則 去匹配原始字符串 被貪婪模式 提醒過的規則果然不負眾望, 一次提一串連著的 ‘333‘ findall 拿著它 提取了 兩次 ,就把所有數字提取出來了 結果就是 ["333", "333"] 非貪婪: import re r1 = re.compile(r"d+?") print(r1.findall("你好333你好333你好")) >>> ["3", "3", "3", "3", "3", "3"] 解釋: 規則 同樣是 匹配至少一位數字。 但是 非 貪婪模式 提醒了 規則:“你的任務是給我盡可能的 少 匹配數字” findall 拿著 被貪婪化的 規則 去匹配原始字符串 被貪婪模式 提醒過的規則果然不負眾望, 一次只提取一個 ‘3‘ findall 拿著它 提取了 六次 ,才把所有數字提取出來了 結果就是 ["3", "3", "3", "3", "3", "3"]匹配方法
match(): """ match()方法是 根據規則從第一個開始,向后逐個匹配,如果有一個字符匹配不上,就返回None """ s = "hello python" re1 = re.compile(r"he") re1.match("") result = re1.match(s).group() if re1.match(s) else None # 注意:非None才有group方法 print(result) # 通過 group()方法獲得的才是最終 正則匹配的字符串 >>> he 簡單分組提取: s = "hello python" re1 = re.compile(r"h(e)llo") # 給e加個一個(),就代表添加了分組,一會要把他提出來 result = re1.match(s).group(1) if re1.match(s) else None # 注意上方的 group(1) 這個參數是1,代表 只 提取 分組 里面的內容 >>> e # 如果是 group() 或 group(0) 代表提取 整個正則規則 的內容 >>> hello print(result) >>> e 嵌套-平行(深度-廣度)分組提取: 原理:分組提取先提取嵌套的,后提取平行的 (專業點就是先深度,后廣度) eg: a = "123-%%%-dd" result = re.compile(r"123(-(%%%)-)d(d)").match(a).groups() # 或者用 group(1), group(2), group(3) 代替groups() 單個看也行 print(result) >>> ("-%%%-", "%%%", "d") search(): """ search() 方法是: 從前向后按規則‘搜索’, 直到搜到位置,搜不到就返回None """ s = "aaa123aaa" r1 = re.compile(r"d+").search(s).group() print(r1) >>> 123 findall(): """ findall() 方法是: 按照正則規則,搜索所有符合規則的字符串,以列表的形式作為結果返回 """ s = "aaa---123---bbb" r1 = re.compile(r"w+").findall(s) print(r1) >>> ["aaa", "123", "bbb"] 微不足道的擴展: a = "123-%%%-dd" result = re.compile(r"-(.*?)-").findall(a) print(result) >>> %%% # 解釋: findall() 方法中 如果規則中含有分組,那么就會只返回分組中提取的的內容 finditer(): """ finditer() 和 findall() 使用方式一樣,只不過返回結果是 可迭代對象,easy,此處不在多說 """ split(): """ split()方法是:按照規則去切割,切割結果以列表的方式返回 """ 語法關聯: 我們知道字符串 有 split() 方法,可以按照一個參數損耗來切割,但是這個參數只能指定一個 如果讓你在多種規則的前提下切割,需要怎么辦。 巧了,正則切割split() 方法就是解決這個問題的, 實例如下: s = "aaa%%123@@bbb" # 可以看見,%和@符號把字符分開了,現在我們只想要字符 r1 = re.compile(r"W+").split(s) # W 大寫: 以非單詞性字符作為損耗規則,來切割 print(r1) >>> ["aaa", "123", "bbb"] sub(): """ sub()方法是: 按照規則匹配選出代替換的字符,然后自己 給定字符去替換 """ 場景1:常用方式,自己給定目標字符串,按規則匹配并直接替換原始字符串 eg: s = "aaa%%123@@bbb" r1 = re.compile(r"W+").sub("你好",s) print(r1) >>> aaa你好123你好bbb 場景2:正則匹配后的結果 經過函數操作,函數的返回值作為 替換的最終結果 eg: s = "aaa%%123@@bbb" r1 = re.compile(r"W+").sub(lambda a:a.group()*2, s) print(r1) >>> aaa%%%%123@@@@bbb 解釋: 按照規則匹配到的字符是 %%和@@,經過函數 乘以2后, 就替換成了 %%%%和@@@@ subn(): """ subn() 和 sub()語法幾乎一樣,唯一的擴展功能就是 返回結果是元組,(字符串, 次數) """ s = "aaa%%123@@bbb" r1 = re.compile(r"W+").subn("你好",s) print(r1) >>> ("aaa你好123你好bbb", 2)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45093.html
摘要:解釋就相當于把每個序列元素的每一個單獨用一個管道函數處理,再把他們按順序組合成一個新可迭代對象注意這個管道函數只能是單參數函數,如果想傳遞多個參數怎么辦使用偏函數怕有些人看不懂,這里就不用了,而是用普通函數定義方式固定值固定值固定值固定值固 map In [25]: list(map(lambda a:a**2, [1,2,3,4])) Out[25]: [1, 4, 9, 16] 解...
摘要:不要疑惑,告訴你答案這個代表正負號的正。雖然一點技術含量沒有,但是你要懂序列也許叫可迭代對象更為合適,但是我喜歡叫序列。 數據結構 可變類型與不可變類型(重頭戲) 基操: 可變類型:[], {} # 可增刪改 查 不可變類型: int float str () # 無法增刪改, 只可查 升操: + 與...
摘要:多線程對于爬蟲方面也可以表現出較好的性能。計算密集型就別想多線程了,一律多進程。所以同一時刻最大的并行線程數進程數的核數這條我的個人理解很模糊,參考吧多線程多線程有種通過的那種方式,非常普遍,此處就不寫了。 GIL的理解 GIL這個話題至今也是個爭議較多的,對于不用應用場景對線程的需求也就不同,說下我聽過的優點: 1. 我沒有用過其他語言的多線程,所以無法比較什么,但是對于I/O而言,...
摘要:類的繼承類繼承有三種調用方式,其實是有區別的,聽我慢慢道來第一種父類方法參數直接調用第二種方法參數直接調用在誰的類下調用,就找此類對應的下一個就是要繼承的第三種方法參數找類名對應的的下一個,就是繼承的,一般寫本身的類名上下文管理器上下文管理 類的繼承 類繼承有三種調用方式,其實是 有區別 的,聽我慢慢道來 class A: def say(self, name): ...
摘要:也就是給原函數加個外殼。類裝飾填充了啊我是原函數類裝飾填充了啊我是原函數說明后面關于類的裝飾器如果理解困難當做了解即可,用的也少。 可迭代對象、生成器、迭代器三者的關系 1. 迭代器一定是可迭代對象 2. 生成器是迭代器的一種 3. 可迭代對象:必須實現 __iter__方法 4. 迭代器:必須實現 __iter__方法 和 __next__ 方法 5. 生成器:必須實現 __it...
閱讀 2894·2021-08-20 09:37
閱讀 1618·2019-08-30 12:47
閱讀 1106·2019-08-29 13:27
閱讀 1694·2019-08-28 18:02
閱讀 758·2019-08-23 18:15
閱讀 3097·2019-08-23 16:51
閱讀 940·2019-08-23 14:13
閱讀 2159·2019-08-23 13:05