🍖re 模塊

引入

正則表達式是匹配字符串的強大工具, 在每一個編程語言中都有正則表達式的概念, 利用正則表達式, 咱們從返回的頁面內容中提取想要的內容就變的比較方便了python

1.什麼是 re 模塊

  • re 模塊是 Python 內置的模塊

2.什麼是正則

  • 正則表達式是對字符串操做的一種邏輯 (規則), 就是事先定義好一些特定的字符組合, 組成一個"規則字符串", 而後使用這個 "規則字符串" 來對字符串進行過濾
  • Python 中經過內置的 re 模塊來使用正則表達式, 它提供了全部正則表達式的功能

3.正則表達式的大體匹配過程

  • 定義一個"規則字符串", 而後依次與文本中的字符進行對比
  • 若是每個字符都能匹配, 那麼就匹配成功, 不然匹配失敗
  • 若是表達式中有量詞或者邊界, 這個過程會稍微有一些不一樣

4.正則小示例

  • 好比咱們描述四條腿的東西 (規則字符串), 咱們可能會想到的有四條腿的動物, 桌子和椅子等等
  • 好比咱們描述條腿的東西而且是活的, 咱們可能會想到人類, 猴子, 鳥, 袋鼠, 雞麼等等

006APoFYjw1f90pqirctog3046046ta3

5.經常使用正則表達式表

模式 描述
\w 匹配字母數字及下劃線
\W 匹配非字母數字下劃線
\s 匹配任意空白字符,等價於[\t,\n,\r,\f]
\S 匹配任意非空字符
\d 匹配任意數字,等價於[0-9]
\D 匹配任意非數字
\A 匹配以xx字符串開始
\Z 匹配xx字符串結束,若是是存在換行,只匹配到換行前的結束字符串
\z 匹配xx字符串結束
\G 匹配最後匹配完成的位置
\n 匹配一個換行符
\t 匹配一個製表符
^ 匹配字符串的開頭
$ 匹配字符串的末尾
. 匹配任意字符, 除了換行符, 當 re.DOTALL 標記被指定時, 則能夠匹配包括換行符的任意字符
[...] 用來表示一組字符, 單獨列出:[amk] 匹配 'a','m' 或 'k'
[^...] 不在 [ ] 中的字符:[^abc] 匹配除了a, b, c以外的字符
* 匹配0個或多個的表達式
+ 匹配1個或多個的表達式
? 匹配0個或1個由前面的正則表達式定義的片斷,非貪婪方式
{n} 精確匹配n個前面表達式。
{n,m} 匹配n到m次由前面的正則表達式定義的片斷,貪婪方式
alb 匹配a或b
() 匹配括號內的表達式,也表示一個組

ps : [...] 講解 : [ ]全部的特殊字符在字符集中都失去其原有的特殊含義,在字符集中若是要使用]-^,能夠在前面加上反斜槓,或把]-放在第一個字符,把^放在非第一個字符正則表達式

更多正則表達式 : https://www.jb51.net/tools/regexsc.htm編程

一.普通字符和元字符

正則表達式就是由一些普通字符和元字符組成的編程語言

  • 普通字符就是字母和數字
  • 元字符就是具備特殊意義的字符, 經常使用於表單驗證

二.正則邊界(定位字符)

  • ^ : 會匹配字符串或者行的起始位置, 在 [ ] 中表示 ''非''(!)
  • $ : 會匹配字符串或行的結束位置 (在 \n 以前)
  • ^,$ 一塊兒則表示精確匹配包裹在兩個符號之間的字符串
  • \A : 指定匹配必須出如今字符串的開頭(忽略 Multiline 選項)
  • \Z : 指定匹配必須出如今字符串的結尾或字符串結尾的 \n 以前(忽略 Multiline 選項)

三.量詞

  • : 重複零次或更多 (>=0)函數

  • : 重複一次或更屢次 ( >=1)工具

  • : 重複零次或一次 (0 || 1)spa

  • {} : 重複多少次的意思 能夠有多少個.net

四.經常使用的功能函數

函數 說明
re.match( ) 從字符串的起始位置匹配, 匹配成功, 返回一個匹配的對象, 不然返回None
re.search( ) 掃描整個字符串並返回第一個成功的匹配
re.findall( ) 在字符串中找到正則表達式所匹配的全部子串, 並返回一個列表, 若是沒有找到匹配的, 則返回空列表
re.split( ) 將一個字符串按照正則表達式匹配結果進行分割, 返回列表類型
re.finditer( ) 在字符串中找到正則表達式所匹配的全部子串, 並把它們做爲一個迭代器返回
re.sub( ) 把字符串中全部匹配正則表達式的地方替換成新的字符串
re.complie( ) 將正則表達式傳入, 返回一個匹配對象, 通常與其餘方法組合使用

五.正則使用示例

💠一對一匹配

print("hello".replace("llo","ooo"))  # heooo
print("hello".find("abcd"))  # -1 (找不到返回 -1)
print("hello".find("he"))    # 0

💠正則匹配

  • \w\W
import re

print(re.findall("\w","ab* 12$ _"))  # ['a', 'b', '1', '2', '_']
print(re.findall("\W","ab* 12$ _"))  # ['*', ' ', '$', ' ']
  • \s\S
print(re.findall("\s","ab* 12$ _ "))  # [' ', ' ', ' ']
print(re.findall("\S","ab* 12$ _ "))  # ['a', 'b', '*', '1', '2', '$', '_']
  • \d\D
print(re.findall("\d","ab* 12$ _"))  # ['1', '2']
print(re.findall("\D","ab* 12$ _"))  # ['a', 'b', '*', ' ', '$', ' ', '_']
  • \A\Z
print(re.findall("\Aab","ab* 12$ _"))  # ['ab']
print(re.findall("\Aaa","ab* 12$ _"))  # [] 沒匹配到爲空
print(re.findall("_\Z","ab* 12$ _"))   # ['_']
print(re.findall("0\Z","ab* 12$ _"))   # [] 沒匹配到爲空
  • \t\n
print(re.findall("\t","ab* 12$ \t_"))    # ['\t']
print(re.findall("\n","ab* 12$ \n_"))    # ['\n']

🔰"\s" 能夠匹配"\t"和"\n"
print(re.findall("\s","ab* \t12$ _\n"))  # [' ', '\t', ' ', '\n']
  • ^\$
print(re.findall("^ab","ab* 12$ _"))   # ['ab']
print(re.findall("_$","ab* 12$ _\n"))  # ['_']

💠重複匹配

  • : 匹配一個任意字符
print(re.findall("a.b","a&b"))  # ['a&b']
print(re.findall("a.b","a2b"))  # ['a2b']
print(re.findall("a.b","acb"))  # ['acb']
print(re.findall("a.b","a b"))  # ['a b']
print(re.findall("a.b","a\tb")) # ['\t']
print(re.findall("a.b","a\nb")) # [] (換行符匹配不到,匹配爲空)
print(re.findall("a.b","a b a*b abb a_b"))  # ['a b', 'a*b', 'abb', 'a_b']
print(re.findall("a.b","a\nb",re.S))        # ['a\nb'] (加入參數, 包含換行)
print(re.findall("a.b","a\nb",re.DOTALL))   # ['a\nb'] (同上效果同樣)
  • : 匹配零個或多個
print(re.findall("a*","aaaa aa"))        # ['aaaa', '', 'aa', ''] (零個或多個a)
print(re.findall("ab*","abab aa"))       # ['ab', 'ab', 'a', 'a'] (一個a零個或多個b)
print(re.findall("a*b","ababaaaba aa"))  # ['ab', 'ab', 'aaab'] (零個或多個a一個b)
print(re.findall("ab*","bbbbbbbb"))      # [] (沒有匹配到一個a零個或多個b)
  • : 匹配零個或一個
print(re.findall("ab?","a"))     # ['a']
print(re.findall("ab?","abbb"))  # ['ab']
  • : 匹配一個或多個
print(re.findall("a+","bbb"))    # []
print(re.findall("a+","ab"))     # ['a']
print(re.findall("ab+","ab"))    # ['ab']
print(re.findall("ab+","abbb"))  # ['abbb']
  • {n,m} : 匹配 n~m 之間個
print(re.findall("a{9}","aaaa"))     # [] (匹配9個b,沒有)
print(re.findall("a{3}","aaaa"))     # ['aaa']
print(re.findall("a{2}","aaaa"))     # ['aa', 'aa']
print(re.findall("ab{2}","aabbb"))   # ['abb']
print(re.findall("ab{2,6}","abbb"))  # ['abbb'] (一個a,2~6個b)
print(re.findall("ab{1,}","abbb"))   # ['abbb'] (至關於 ab+)
print(re.findall("ab{0,}","abbb"))   # ['abbb'] (至關於 ab*)
  • [ ] : 放一組字符,逐個匹配
print(re.findall("a[*1_c-]b","a*ba1b a_baaba-b"))     # ['a*b', 'a1b', 'a_b', 'a-b']
print(re.findall("a[^*1c-]b","a*ba1b a_baab"))        # ['a_b', 'aab'] (匹配非 [] 內的字符)
print(re.findall("a[0-9]b","a*ba1b a3baa2b"))         # ['a1b', 'a3b', 'a2b'] (0~9)
print(re.findall("a[a-z]b","a*banb apbaaob"))         # ['anb', 'apb', 'aob'] (a~z)
print(re.findall("a[a-zA-Z0-9]b","a*banb aPbaa7b"))   # ['anb', 'aPb', 'a7b']
print(re.findall("a[^a-zA-Z0-9]b","a*banb aPbaa7b"))  # ['a*b'] (非a~z,A~Z,0~9)
  • ( ) : 分組
print(re.findall('ab+','ababab123')) 
# ['ab', 'ab', 'ab']
print(re.findall('(ab)+123','ababab123')) 
# ['ab'],匹配到末尾的 ab123 中的 ab
print(re.findall('(?:ab)+123','ababab123')) 
# findall的結果不是匹配的所有內容,而是組內的內容, ?: 可讓結果爲匹配的所有內容
print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">點擊</a>'))
# ['http://www.baidu.com']
print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">點擊</a><a href="http://www.aiqiyi.com">點擊2</a>'))
# ['href="http://www.baidu.com"', 'href="http://www.aiqiyi.com"']
  • a|b : 左右兩邊都匹配
print(re.findall("shawn|song","shawn is man song is shawn"))  # ['shawn', 'song', 'shawn'] (不加括號全局匹配)
print(re.findall("A(?:abc|cba)A","AabcA"))  # ['AabcA']
print(re.findall("com(?:puter|e)","come on! Here is a computer "))  # ['come', 'computer']
  • \ : 轉義字符
# 轉義字符,使後一個字符改變原來的意思。
# 若是字符串中有字符 * 須要匹配,可使用 \* 或者字符集 [*]
print(re.findall("a.b","a1b a.b"))   # ['a1b', 'a.b']
print(re.findall("a\.b","a1b a.b"))  # ['a.b']

💠匹配全部數字類型示例

print(re.findall("\d+\.?\d*","12as3.45qw2k7"))  # ['12', '3.45', '2', '7']

💠.* 貪婪匹配示例

  • 匹配更多的字符
print(re.findall("a.*b","a11b22222b33"))  # ['a11b22222b']

💠.*? 非貪婪匹配示例

  • 儘量少的匹配
print(re.findall("a.*?b","a11b22222b3"))  # ['a11b']

六. re 模塊經常使用方法示例

一、re.findall( pattern,string)

  • 返回全部知足匹配的結果, 按照順序依次放入列表中, 若是沒有匹配結果, 返回一個空列表
print(re.findall("abc","112abc333"))  # ['abc']
print(re.findall("abcd","12abc333"))  # []

二、re.search( pattern,string)

  • 匹配整個字符串, 只到找到第一個匹配而後返回一個包含匹配信息的對象(re.Match對象)
  • 該對象能夠經過調用 group( ) 方法獲得匹配的字符串,若是字符串沒有匹配,則返回None
  • 若是沒有匹配到值就調用 group( ) 方法, 拋出異常
print(re.search("abc","112abc333abc"))  
# <re.Match object; span=(3, 6), match='abc'>
print(re.search("abc","112abc333abc").group())  # abc

print(re.search("abcd","12abc333abc"))          # None
print(re.search("abcd","12abc333abc").group()) 
# 報錯 "AttributeError" (由於沒拿到這個對象,因此沒有group()屬性

三、re.match( pattern,string)

  • re.search 功能相同, 但必須匹配起始位置, 否則返回 None
  • 可使用上尖號 ^ : re.search("^abc","abc") 實現 re.match() 功能?
print(re.match("abc","abc22abc"))  # <re.Match object; span=(0, 3), match='abc'>
print(re.match("abc","abc22abc").group())  # abc

print(re.match("abc","1abc22abc"))  # None
print(re.search("^abc","1abcabc"))  # None  (re.search)

四、re.split( pattern,string)

  • 規定字符做爲分隔符對字符串進行切分, 切分結果放入列表, 沒匹配到返回原字符串列表
  • 將規定字符放入 [ ] 則是逐個匹配
print(re.split("o","abcoabcoabc"))   # ['abc', 'abc', 'abc']
print(re.split("ab","abcoabcoabc"))  # ['', 'co', 'co', 'c']

print(re.split("d","abcoabcoabc"))  # ['abcoabcoabc'] (沒匹配到返回原字符串)

print(re.split("[o]","abcoabcoabc"))  # ['abc', 'abc', 'abc']
print(re.split("[ob]","abcoabcoabc"))   # ['a', 'c', 'a', 'c', 'a', 'c']
print(re.split("[oba]","abcoabcoabc"))  # ['', '', 'c', '', '', 'c', '', '', 'c']
# 先使用"o"匹配進行分隔, 獲得結果"['abc', 'abc', 'abc']", 在使用"b"進行匹配分隔,獲得結果後再使用"a"匹配進行分隔

五、re.sub( ) 和 re.subn( )

  • 匹配"規則字符", 並將其該成指定字符, 返回改變後的字符串, 後面可跟個數參數, 不指定默認替換全部
  • re.subn( ) 返回一個元組, 第二個元素返回的是替換的個數
print(re.sub("a","A","i am a man"))   # i Am A mAn
print(re.sub("a","b","i am a man"))   # i bm b mbn
print(re.sub("am","b","i am a man"))  # i b a man
print(re.sub("a","AA","i am a man"))  # i AAm AA mAAn

print(re.sub("a","A","i am a man",1))  # i Am a man
print(re.sub("a","A","i am a man",2))  # i Am A man
print(re.sub("a","A","i am a man",3))  # i Am A mAn
print(re.sub("a","A","i am a man",9))  # i Am A mAn (超出字符串中最大的個數不會報錯,而是替換全部)

print(re.subn("a","A","i am a man"))    # ('i Am A mAn', 3) (顯示替換的個數)
print(re.subn("a","A","i am a man",2))  # ('i Am A man', 2)

六、re.compile( )

  • 在該函數中傳入"規則字符", 返回一個對象, 它單獨使用沒有任何意義, 須要和 findall( ), search( ), match( ) 組合使用
obj = re.compile("\d{2}")
print(obj)  # re.compile('\\d{2}')

print(obj.findall("ab12c33b44"))         # ['12', '33', '44']
print(obj.search("ab12c33b44").group())  # 12
print(obj.match("12c33b44").group())     # 12 (注意,必須在開頭就匹配到,否則group會報錯)

七.補充非捕獲模式 : ?: ?! ?=

字符 描述
(?:pattern) 匹配pattern, 但不捕獲匹配結果。
(?=pattern) 零寬度正向預查,不捕獲匹配結果。
(?!pattern) 零寬度負向預查,不捕獲匹配結果。
(?<=pattern) 零寬度正向回查,不捕獲匹配結果。
(?<!pattern) 零寬度負向回查,不捕獲匹配結果。

一、?! 示例

  • ?! pattern,表示在沒有配到pattern的字符串的前提下,再進行後續的正則表達式匹配,後續匹配仍然從被匹配字符串的頭開始
🍓 匹配密碼,密碼必須是由6位數字與字母組成,而且不能是純數字也不能是純字母
while 1:
    passwd = input(">>").strip()
    res = re.match("(?![\d]+$)(?![a-zA-Z]+$)[\da-zA-Z]{6}$",passwd)
    if res:
        print(f"密碼:{res.group()}")
    else:
        print("密碼不符合規則")

二、?= 示例

  • ?= pattern,表示在配到pattern的字符串的前提下,再進行後續的正則表達式匹配,後續匹配仍然從被匹配字符串的頭開始
🍓 匹配密碼,必須包含大寫,小寫和數字,和特殊字符(!,@,#,%,&),且大於6位
while 1:
    passwd = input("請輸入密碼>>").strip()
    res = re.search("(?=.*[\d])(?=.*[a-z])(?=.*[A-Z])(?=.*)(?=.*[!@#%&])^([\da-zA-Z!@#%&]{7,})$",passwd)
    if res:
        print(res.group())
    else:
        print("密碼強度不夠")
相關文章
相關標籤/搜索