正規表達式
re子產品引入
re子產品是python一共的專門支援這個則表達式的一個子產品
fullmatch函數:
fullmatch(正規表達式,字元串) - 讓正規表達式和指定字元串驚醒完全比對,如果比對失敗傳回None;
正則文法
正規表達式 - 正規表達式是一個讓字元串複雜問題變得簡單的工具
寫正規表達式的主要工作:用正則符号描述清楚相關字元串的規則
1)普通字元(普通符号)
在正則除了有特殊功能或者特殊意義以外的符号
普通字元在正則中表示這個符号本身
python正則表示方式:r’正規表達式’
js的正則:/正規表達式/
2). - 比對任意一個字元
re_str = r'a.c'
print(fullmatch(re_str, 'abc'))
3)\d - 比對任意一個數字字元
re_str = r'a\d\dc'
print(fullmatch(re_str, 'a12c'))
4)\s - 比對任意一個空白字元
空白字元:制表符(\t)、空格、回車(\n)
re_str = r'a\sb'
print(fullmatch(re_str, '''a
b'''))
5)\w - 比對任意一個字母、數字或者下劃線(不好用)
6)
\D - 比對任意一個一個非數字
\S - 比對任意一個非空字元
7)[字元集] - 比對字元集中任意一個字元
注意:一個[]隻能比對一個字元
[多個普通字元] - [abc]可以比對a或者b或者c
[包含\開頭的特殊符号的字元集] - [\dabc],可以比對任意數字或者a或者b或者c
[包含減号在兩個字元之間的字元集] - 這個時候的減号表示誰到誰
注意:減号前面的字元編碼必須小于減号後面的
例如:
[a-z] - 任意一個字母
[a-d] - 比對abcd中任意一個字元
[A-Z] - 比對任意一個大寫字母
[1-9] - 比對1到9中任意一個數字字元
[\u4e00-\u9fa5] - 比對任意一個中文字元
[a-zA-Z]、[A-Za-z] - 任意一個字母
[a-z123] - 比對任意一個小寫字母,或者1或者2或者3
re_str = r'a[xym]b'
print(fullmatch(re_str, 'amb')) # axb ayb amb
8)[^字元集] - 比對任意一個不在字元集任意一個字元
[^abc] - 比對除了a、b、c以外的任意一個字元
[^a-z] - 比對除了小寫字母以外的任意一個字元
注意:[]中的-和^隻有放在指定位置的時候才有特殊功能,否則在[]中就是一個普通的符号
檢測類符号
檢測類符号的存在不影響被比對的字元串長度,它的作用是在比對成功的前提下檢測符号所在的位置是否符合要求
檢測類符号的用法:先去掉檢測類符号,看是否能比對成功,如果失敗整個正則比對失敗。如果成功再來看檢測類符号所在的位置是否符合要求
- \b - 檢測是否是單詞邊界
單詞邊界 - 能夠區分出兩個不同單詞的符号都屬于單詞邊界,例如:空白、标點符号、字元串開頭、字元串結尾
- \B - 檢測是否是非單詞邊界
- ^ - 檢測是否是字元串開頭
- $ - 檢測是否是字元串結尾
比對次數
1.***** - 比對0次或者多次(任意次數)
用法:比對類符号*
a* - 比對任意多個a
\d* - 比對任意多個數字字元
2.+ - 比對一次或多次(至少一次)
3.? - 比對0次或1次
4.{}
{N} - 比對N次
{M,N} - 比對M到N次
{,N} - 比對最多N次
{M,} - 比對最少M次
5.貪婪和非貪婪
在比對次數不确定的時候,比對模式分為貪婪和非貪婪兩種,預設是貪婪模式
在比對成功的前提下,貪婪是比對次數選最多的那個次數;非貪婪是比對次數最少的那個次數
*、+、?、{M,N}、{M,}、{,N} - 貪婪的
*?、+?、??、{M,N}?、{M,}?、{,N}? - 非貪婪的
分組和分支
1.() - 分組
作用1:将()中的内容作為一個整體,進行整體相關操作,例如,整體控制次數
作用2:通過’\M’重複前面第M個分組比對到的結果,M從1開始
作用3:捕獲
str1 = ‘23abc23’
2.| - 分支
正則1|正則2 - 先用正則1進行比對,如果成功就直接比對成功,如果比對失敗再用正則2進行比對
3.轉義符号
在特殊符号前加\,讓符号的功能消失,變成一個普通符号
若果是獨立存在有特殊功能的符号,将符号放入[]中其功能也會自動消失
re子產品
- re.compile
re_obj = re.compile(r'')
re_obj.fullmatch('')
- fullmatch(正規表達式,字元串) - 讓正規表達式和整個字元串進行比對(完全比對),比對失敗傳回None,比對成功傳回比對對象
match(正規表達式,字元串) - 比對字元串開頭
result = re.fullmatch(r'\d{3}', '345')
print(result)
1)擷取比對到的字元串
比對對象.group() / 比對對象.group(0) - 擷取整個正規表達式比對到的結果
比對對象.group(N) - 擷取第N個分組比對到的結果
- search(正規表達式,字元串) - 擷取字元串中第一個滿足正規表達式的子串,傳回結果式None或者比對對象
result = re.search
2)擷取比對結果在原字元串中的位置資訊
比對對象.span() - 傳回的是一個元組,元組中的元素是開始下标和結束下标,結束下标對應的位置取不到
比對對象.span(N)
- findall(正規表達式,字元串) - 擷取字元串中所有滿足正則的子串,傳回的是清單,清單中的元素是子串(沒有分組的時候)
如果正則中隻有一個分組:傳回的清單中的元素是每個分組比對到的結果
如果正則中有兩個或以上分組:傳回的清單中的元素是元組,元組中的元素是每個分組比對到的結果
result = re.findall(r'\d{2}', '34ssd908計算機上23,udh89,試試89123')
print(result) # ['34', '90', '23', '89', '89', '12']
result = re.findall(r'(\d{2})\D', '34ssd908計算機上23,udh89,試試89123')
print(result) # ['34', '08', '23', '89']
result = re.findall(r'((\d[a-z]){2})', '2m4m司機師傅9k0o試試3k5l--')
print(result) # [('2m4m', '4m'), ('9k0o', '0o'), ('3k5l', '5l')]
result = re.findall(r'(\d{2})-([a-z]{3})', '23-msn資料是98-kop聖誕節發貨')
print(result) # [('23', 'msn'), ('98', 'kop')]
- finditer(正規表達式,字元串) - 擷取字元串中所有滿足正則的子串,傳回的是一個疊代器,疊代器是比對對象
result = re.finditer(r'(\d{2})-([a-z]{3})', '23-msn資料是98-kop聖誕節發貨')
print(result)
r1 = next(result)
print(r1, r1.group(), r1.group(1), r1.group(2))
- split(正規表達式,字元串) - 将字元串中所有滿足正規表達式的子串作為切割點,對字元串進行切割
re.split(正規表達式,字元串,N) - 将字元串中前N個滿足正規表達式的子串作為切割點,對字元串進行切割
- sub(正規表達式,字元串1,字元串2) - 将字元串2中所有滿足正規表達式的子串替換成字元串1
- flags參數
上面的每個函數都有個參數flags,用來設定正則參數
1)單行比對和多行比對參數:re.S、re.M(預設)
單行比對:.可以比對\n
多行比對:.不能和\n比對
2)忽略大小寫:re.I
flags=re.S <==> r'(?s)正規表達式'
2) 忽略大小寫:re.I
flags=re.I <==> r'(?i)正規表達式'
flags=re.S|re.I <==> r'(?si)正規表達式'
print(re.fullmatch(r'a.b', 'a\nb', flags=re.M)) # None
print(re.fullmatch(r'a.b', 'a\nb')) # None
print(re.fullmatch(r'a.b', 'a\nb', flags=re.S))
print(re.fullmatch(r'(?s)a.b', 'a\nb'))
print('---------------------------------------------------')
print(re.fullmatch(r'abc', 'abc'))
print(re.fullmatch(r'abc', 'Abc')) # None
print(re.fullmatch(r'abc', 'ABc', flags=re.I))
print(re.fullmatch(r'(?i)abc', 'ABc'))
print(re.fullmatch(r'a.b', 'A\nb', flags=re.S|re.I))
print(re.fullmatch(r'(?is)a.b', 'A\nb'))
作業
利用正規表達式完成下面的操作:
一、不定項選擇題
- 能夠完全比對字元串
和字元串"(010)-62661617"
的正規表達式包括(ABD )"01062661617"
A.
r"\(?\d{3}\)?-?\d{8}"
B.
r"[0-9()-]+"
C.
r"[0-9(-)]*\d*"
D.
r"[(]?\d*[)-]*\d*"
-
能夠完全比對字元串“back”和“back-end”的正規表達式包括( ABCD )
A. r“\w{4}-\w{3}|\w{4}”
B. r“\w{4}|\w{4}-\w{3}”
C.r “\S±\S+|\S+”
D. r“\w*\b-\b\w*|\w*”
-
能夠完全比對字元串“go go”和“kitty kitty”,但不能完全比對“go kitty”的正規表達式包括(AD)
A.r “\b(\w+)\b\s+\1\b”
B. r“\w{2,5}\s*\1”
C. r“(\S+) \s+\1”
D. r“(\S{2,5})\s{1,}\1”
-
能夠在字元串中比對“aab”,而不能比對“aaab”和“aaaab”的正規表達式包括( BC)
A. r“a*?b”
B. r“a{,2}b”
C. r“aa??b”
D. r“aaa??b”
二、程式設計題
1.使用者名比對
要求: 1.使用者名隻能包含數字 字母 下劃線
2.不能以數字開頭
3.⻓度在 6 到 16 位範圍内
import re
a = r'[A-Za-z_][0-9A-Za-z_]{5,15}'
print(re.fullmatch(a, '321231654'))
print(re.fullmatch(a, 'a123456'))
print(re.fullmatch(a, 'b111111111111111111'))
# None
# <re.Match object; span=(0, 7), match='a123456'>
# None
- 密碼比對
要求: 1.不能包含!@#¥%^&*這些特殊符号
2.必須以字母開頭
3.⻓度在 6 到 12 位範圍内
a = r'[a-zA-Z][^!@#¥%^&*]{5,11}'
print(re.fullmatch(a, 'casdf21234'))
print(re.fullmatch(a, 'a123456'))
print(re.fullmatch(a, 'b111111111111111111'))
# <re.Match object; span=(0, 10), match='casdf21234'>
# <re.Match object; span=(0, 7), match='a123456'>
# None
-
ipv4 格式的 ip 位址比對
提示: IP位址的範圍是 0.0.0.0 - 255.255.255.255
a = r'(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
print(re.fullmatch(a, '256.255.255.0'))
print(re.fullmatch(a, '192.168.1.1'))
print(re.fullmatch(a, '255.254.256.128'))
# None
# <re.Match object; span=(0, 11), match='192.168.1.1'>
# None
- 提取使用者輸入資料中的數值 (數值包括正負數 還包括整數和小數在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
a = r'-?\d+\.?\d*'
str1 = '-3.14good87nice19bye'
print(eval('+'.join(re.findall(a, str1))))
- 驗證輸入内容隻能是漢字
a = r'[\u4e00-\u9fa5]*' str1 = '-3.14good87nice19bye' str2 = 'i love 中國' str3 = '我愛中國' print(re.fullmatch(a, str1))# None print(re.fullmatch(a, str2))# None print(re.fullmatch(a, str3))# <re.Match object; span=(0, 4), match='我愛中國'>
- 比對整數或者小數(包括正數和負數)
- 驗證輸入使用者名和QQ号是否有效并給出對應的提示資訊
要求:
使用者名必須由字母、數字或下劃線構成且長度在6~20個字元之間
QQ号是5~12的數字且首位不能為0
usname = 'ljm_121212' qqnum = '21231313245457894' us_check = r'\w{6,20}' qq_check = r'[1-9]\d{5,11}' if re.fullmatch(us_check, usname) == None: print('輸入使用者名錯誤') if re.fullmatch(qq_check, qqnum) == None: print('輸入qq号錯誤')
- 拆分長字元串:将一首詩的中的每一句話分别取出來
poem = ‘窗前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。’
poem = '窗前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。'
a = r'[\u4e00-\u9fa5]{5}'
print(re.findall(a, poem))