天天看點

day16-正規表達式正規表達式作業

正規表達式

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] - 比對除了小寫字母以外的任意一個字元

注意:[]中的-和^隻有放在指定位置的時候才有特殊功能,否則在[]中就是一個普通的符号

檢測類符号

檢測類符号的存在不影響被比對的字元串長度,它的作用是在比對成功的前提下檢測符号所在的位置是否符合要求

檢測類符号的用法:先去掉檢測類符号,看是否能比對成功,如果失敗整個正則比對失敗。如果成功再來看檢測類符号所在的位置是否符合要求

  1. \b - 檢測是否是單詞邊界

單詞邊界 - 能夠區分出兩個不同單詞的符号都屬于單詞邊界,例如:空白、标點符号、字元串開頭、字元串結尾

  1. \B - 檢測是否是非單詞邊界
  2. ^ - 檢測是否是字元串開頭
  3. $ - 檢測是否是字元串結尾

比對次數

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子產品

  1. re.compile
re_obj = re.compile(r'')
re_obj.fullmatch('')
           
  1. fullmatch(正規表達式,字元串) - 讓正規表達式和整個字元串進行比對(完全比對),比對失敗傳回None,比對成功傳回比對對象

match(正規表達式,字元串) - 比對字元串開頭

result = re.fullmatch(r'\d{3}', '345')
print(result)
           

1)擷取比對到的字元串

比對對象.group() / 比對對象.group(0) - 擷取整個正規表達式比對到的結果

比對對象.group(N) - 擷取第N個分組比對到的結果

  1. search(正規表達式,字元串) - 擷取字元串中第一個滿足正規表達式的子串,傳回結果式None或者比對對象

result = re.search

2)擷取比對結果在原字元串中的位置資訊

比對對象.span() - 傳回的是一個元組,元組中的元素是開始下标和結束下标,結束下标對應的位置取不到

比對對象.span(N)

  1. 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')]
           
  1. 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))
           
  1. split(正規表達式,字元串) - 将字元串中所有滿足正規表達式的子串作為切割點,對字元串進行切割

re.split(正規表達式,字元串,N) - 将字元串中前N個滿足正規表達式的子串作為切割點,對字元串進行切割

  1. sub(正規表達式,字元串1,字元串2) - 将字元串2中所有滿足正規表達式的子串替換成字元串1
  2. 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'))
           

作業

利用正規表達式完成下面的操作:

一、不定項選擇題

  1. 能夠完全比對字元串

    "(010)-62661617"

    和字元串

    "01062661617"

    的正規表達式包括(ABD )

A.

r"\(?\d{3}\)?-?\d{8}"

B.

r"[0-9()-]+"

C.

r"[0-9(-)]*\d*"

D.

r"[(]?\d*[)-]*\d*"

  1. 能夠完全比對字元串“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*”

  2. 能夠完全比對字元串“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”

  3. 能夠在字元串中比對“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. 密碼比對

​ 要求: 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
           
  1. 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
           
  1. 提取使用者輸入資料中的數值 (數值包括正負數 還包括整數和小數在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
           
a = r'-?\d+\.?\d*'
str1 = '-3.14good87nice19bye'
print(eval('+'.join(re.findall(a, str1))))
           
  1. 驗證輸入内容隻能是漢字
    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='我愛中國'>
               
  2. 比對整數或者小數(包括正數和負數)
  3. 驗證輸入使用者名和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号錯誤')
               
  4. 拆分長字元串:将一首詩的中的每一句話分别取出來
    ​ poem = ‘窗前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。’
poem = '窗前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。'
a = r'[\u4e00-\u9fa5]{5}'
print(re.findall(a, poem))