Day 17-note_regular

Day 17

補(bǔ)充
  • 重載:
    函數(shù)的重載 -- 函數(shù)名相同但是參數(shù)不同的函數(shù)可以有多個(gè)涮阔,但是python不支持函數(shù)的重載
1. 正則表達(dá)式-符號(hào)(regular)
import re
  1. 講解

    • 正則表達(dá)式就是做字符串匹配的一種工具,很多語(yǔ)言都支持正則語(yǔ)法,正則語(yǔ)法是通用的。
    • python中通過(guò)re模塊中提供的方式來(lái)使用正則丽旅。
    • re.fullmatch(正則表達(dá)式, 字符串) -- 完全匹配忱屑,檢查字符串是否滿足正則表達(dá)式的要求篮昧;如果不匹配結(jié)果就是None,匹配結(jié)果是一個(gè)匹配對(duì)象午磁。
    • python正則表達(dá)式 -- r'正則' (r-阻止轉(zhuǎn)義)
    • js正則表達(dá)式 -- /正則/
  2. 匹配字符的符號(hào)
    1)普通字符
    普通字符在正則中代表字符本身尝抖,例如:a, b, 1...等
    要求一個(gè)字符串有5個(gè)字符,分別是h, e, l, l, o

    re_str = r'hello'
    result = re.fullmatch(re_str, 'hello')
    print(result)
    

    2).(匹配除換行符以外的任意字符)
    一個(gè).匹配一個(gè)除換行符以外的任意字符
    [^\n] == .
    匹配一個(gè)字符串有三個(gè)字符迅皇,第一個(gè)字符是a昧辽,最后一個(gè)字符是c,第二個(gè)字符是任意字符

    re_str = r'a.c'
    result = re.fullmatch(re_str, 'a+c')
    print(result)
    

    3)\w(匹配字母登颓、數(shù)字搅荞、下劃線)
    一個(gè)\w只能匹配一個(gè)字符
    注意:這個(gè)不嚴(yán)謹(jǐn),還可以匹配中文等字符,不能匹配ASCII碼表中除了字母數(shù)字下劃線以外的符號(hào)框咙。
    匹配一個(gè)字符串第一個(gè)字符是字母咕痛、數(shù)字、下劃線喇嘱,后面是'abc'

    re_str = r'\wabc'
    result = re.fullmatch(re_str,'_abc')
    print(result)
    

    4)\s(匹配空白字符)
    空白字符:空格茉贡、\t、\n
    一個(gè)\s只能匹配一個(gè)空白字符
    匹配一個(gè)長(zhǎng)度是8的字符者铜,要求前三個(gè)字符是任意字符腔丧,中間兩個(gè)空白字符放椰,后面再三個(gè)任意字符

    re_str = r'...\s\s...'
    result = re.fullmatch(re_str, 'sdf\t\nsdf')
    print(result)
    

    5)\d(匹配數(shù)字字符)

    re_str = r'\d\dabc'
    result = re.fullmatch(re_str, '34abc')
    print(result)
    

    6)\W(非數(shù)字、字母愉粤、下劃線)
    7)\S(非空白字符)
    匹配一個(gè)長(zhǎng)度是4的字符砾医,后面三個(gè)字符是'abc',第一個(gè)字符可以是任何一個(gè)非空白字符

    re_str = r'\Sabc'
    result = re.fullmatch(re_str, '2abc')
    print(result)
    

    8)\D(匹配非數(shù)字字符)

    re_str = '\Dabc'
    result = re.fullmatch(re_str, 'sabc')
    print(result)
    

    9)[](匹配字符集中的一個(gè)字符)

    a.[普通字符集]  --  匹配字符集中的任意一個(gè)字符
    b.[字符1-字符2]  --  匹配字符1到字符2中的任意一個(gè)字符(要求  字符1的編碼值小于字符2)
    [0-9]  --  匹配所有的數(shù)字
    [a-z]  --  匹配小寫字母
    [A-Z]  --  匹配大寫字母
    [a-zA-Z]  --  匹配所有的字母
    [\da-zA-Z_]  --  匹配字母數(shù)字下劃線
    [\u4e00-\u9fa5]  --  匹配所有的中文
    注意:一個(gè)[]只能匹配一個(gè)字符
    

    匹配一個(gè)長(zhǎng)度是4的字符串科汗,第一個(gè)字符是x或者y或者z藻烤,后面是abc

    re_str = r'[xyz]abc'
    result = re.fullmatch(re_str, 'xabc')
    print(result)
    

    匹配一個(gè)長(zhǎng)度是4 的字符串,第一個(gè)字符是數(shù)字或者x, y, z

    re_str = r'[\dxyz]abc'
    result = re.fullmatch(re_str, '4abc')
    print(result)
    

    匹配一個(gè)長(zhǎng)度是4的字符串头滔,第一個(gè)字符是數(shù)字字符2-8中的一個(gè)或者是x,y,z

    re_str = r'[2-8xyz]abc'
    result = re.fullmatch(re_str, '3abc')
    print(result)
    

    匹配一個(gè)長(zhǎng)度是4的字符串怖亭,第一個(gè)字符是漢字

    re_str = r'[\u4e00-\u9fa5]abc'
    result = re.fullmatch(re_str, '以abc')
    print(result)
    
    • [^]
    [^字符集]  --  匹配不在字符集中任意一個(gè)字符
    [^\u4e00-\u9fa5]  --  匹配一個(gè)非中文字符
    ...
    

    匹配一個(gè)長(zhǎng)度是4的字符串,第一個(gè)字符不是中文字符

    re_str = r'[^\u4e00-\u9fa5]abc'
    result = re.fullmatch(re_str, '7abc')
    print(result)
    
  3. 檢測(cè)字符的符號(hào)
    1)\b(檢測(cè)單詞邊界)

    \b  --  檢查\b所在的位置是否是單詞邊界
    單詞邊界  --  字符串開(kāi)頭坤检、字符串結(jié)尾兴猩、空白、標(biāo)點(diǎn)符號(hào)等
    

    匹配一個(gè)長(zhǎng)度是4的字符串早歇,第一個(gè)字符是任意字符倾芝,后邊是abc;檢查c的后面是否是單詞邊界

    re_str = r'.abc\b,are'
    print(re.fullmatch(re_str, '7abc,are'))
    

    2)^(檢查是否是字符串開(kāi)頭)

    re_str = r'^abc'
    print(re.fullmatch(re_str, 'abc'))
    print(re.search(r'\d\d', 'has34ahfskf'))
    

    3)$(檢測(cè)是否是字符串結(jié)尾)

    re_str = r'sfj$'
    print(re.fullmatch(re_str, 'sfj'))
    print(re.search(r'\d\d$', 'hello45'))
    
  4. 轉(zhuǎn)義符號(hào)
    轉(zhuǎn)義符號(hào):通過(guò)在正則中有特殊功能或者意義前加'\',讓這個(gè)正則符號(hào)變成普通符號(hào)
    注意:除了^放在[]開(kāi)頭箭跳,和-放在兩個(gè)字符之間以外晨另,其他單獨(dú)的特殊符號(hào),在[]沒(méi)有特殊功能都是表示字符本身
    只要有歧義的時(shí)候谱姓,就加''

    re_str = r'\d\d\.\d\d'
    print(re.fullmatch(re_str, '34.34'))
    
    re_str = r'\^\d\d\d'
    print(re.fullmatch(re_str, '^344'))
    
    re_str = r'\\d\d\d\d'
    print(re.fullmatch(re_str, '\d344'))
    
    re_str = r'\d\d[.]\d\d'
    print(re.fullmatch(re_str, '34.64'))
    

    ^在[]中不是在開(kāi)頭就沒(méi)有特殊意義

    re_str = r'\d\d[a^-]\d\d'
    print(re.fullmatch(re_str, '34^64'))
    

    -在[]中只要不是放在兩個(gè)字符之間都表示-本身

    re_str = r'\d\d[-]\d\d'
    print(re.fullmatch(re_str, '34-64'))
    re_str = r'\d\d[-a]\d\d'
    print(re.fullmatch(re_str, '34-64'))
    

    []里有字符1借尿,-,a屉来,]

    re_str = r'\d\d[1\-a\]]\d\d'
    print(re.fullmatch(re_str, '34]64'))
    print(re.fullmatch(re_str, '34-64'))
    
  5. 匹配次數(shù)
    1)*(匹配0次或多次)

    字符*  --  指定的字符出現(xiàn)0次或者多次
    a*  --  字符a匹配0次或者多次
    \d*  --  數(shù)字匹配0次或者多次
    [a-z]* -- 小寫字母匹配0次或者多次
    
    re_str = r'a*bc'
    print(re.fullmatch(re_str, 'bc'))
    print(re.fullmatch(re_str, 'abc'))
    print(re.fullmatch(re_str, 'aabc'))
    

    2)+(匹配1次或者多次)
    匹配一個(gè)字符串開(kāi)頭是a,結(jié)束是b,中間至少一個(gè)數(shù)字

    re_str = r'a\d+b'
    print(re.fullmatch(re_str, 'a89b'))
    re_str = r'a\d\d*b'
    print(re.fullmatch(re_str, 'a69b'))
    

    3)?(0次或1次)
    練習(xí):寫一個(gè)正則表達(dá)式路翻,能夠匹配一個(gè)整數(shù)字符串
    283 -73、+7,67, 9

    re_str = r'[+-]?\d+'
    print(re.fullmatch(re_str, '-24'))
    print(re.fullmatch(re_str, '+24'))
    print(re.fullmatch(re_str, '4'))
    print(re.fullmatch(re_str, '-246986654'))
    

    4){}

    {N}  -  匹配N次
    {M,N} - 匹配至少M(fèi)次茄靠,最多N次
    {M,}  -  匹配至少M(fèi)次
    {,N}  -  匹配最多N次
    * == {0,}
    + == {1,}
    ? == {0,1}
    
    re_str = r'\d{4}'
    print(re.fullmatch(re_str, '8273'))
    
    re_str = r'\d{2,4}'
    print(re.fullmatch(re_str, '889'))
    
    re_str = r'[xyz]{,3}'
    print(re.fullmatch(re_str, 'xy'))
    

    練習(xí):寫一個(gè)正則表達(dá)式判斷密碼是否符號(hào)要求:密碼由數(shù)字和字母組成茂契,并第一個(gè)字符是大寫字母,長(zhǎng)度是6-12位

    re_str = r'[A-Z][a-zA-Z\d]{5,11}'
    print(re.fullmatch(re_str, 'A27ggh342h'))
    

    5)非貪婪(~)

    1)貪婪 - 匹配次數(shù)不確定的時(shí)候盡可能多的匹配 (上面次數(shù)不確定的符號(hào)都是貪婪的)
    2)非貪婪 - 匹配次數(shù)不確定的時(shí)候盡可能少的匹配 (上面次數(shù)不確定的符號(hào)后面加?就會(huì)變成非貪婪)
    *? - 0次或多次, 盡可能少
    +? - 1次或多次, 盡可能少
    ?? - 0次或1次, 盡可能少
    {N,M}?
    {M,}?
    {,N}?
    
    re_str = r'a+?'
    print(re.search(re_str, 'A2aaaaaa2h'))
    
    re_str = r'a.+?b'
    print(re.search(re_str, 'a23bgshjsb===='))
    
    re_str = r'a.*b'
    print(re.search(re_str, 'a23bhksdb===='))
    
  6. 分支和分組
    1)|(分支)

    正則1|正則2  --  先用正則1進(jìn)行匹配慨绳,如果匹配失敗再用正則2匹配(正則1和正則2中只要有一個(gè)匹配成功就成功掉冶,兩個(gè)失敗了才會(huì)失敗)
    

    注意:如果正則1匹配成功了,不會(huì)再使用正則2去匹配

    匹配一個(gè)字符串脐雪,開(kāi)頭是abc或者xyz厌小,后面是123
    'abc123' ,'xyz123'
    ?```python
    re_str = r'abc|xyz'
    print(re.fullmatch(re_str, 'abc'))
    
    re_str = r'\d{3}|xyz[a-zA-Z]{4}|\+{3}'
    print(re.fullmatch(re_str, '+++'))
    

    2)() (分組)

    將部分正則作為一個(gè)整體
    1.整體區(qū)分
    (xxx|yyy)[A-Z]{2}[a-z]{2}\d{2}
    2.整體操作
    (\d{2}[a-zA-Z{2}]){3}
    3.整體重復(fù)
    \M  --  重復(fù)前面第M個(gè)匹配到的內(nèi)容
    

    匹配一個(gè)字符串是xxx123,yyy123

    re_str = r'(xxx|yyy)123'
    print(re.fullmatch(re_str, 'xxx123'))
    print(re.fullmatch(re_str, 'yyy123'))
    
    re_str = r'(\d{2}[a-zA-Z]{2}){3}'
    print(re.fullmatch(re_str, '12AB34GH24JK'))
    

    89sdf89,67sfd67

    re_str = r'(\d\d\d)abc\1'
    print(re.fullmatch(re_str, '123abc123'))
    re_str = r'(\d{3})([a-z]{2})\2\1\2'
    print(re.fullmatch(re_str, '123asas123as'))
    
2. 正則表達(dá)式-方法(regular)
from re import *
  1. (了解)compile(正則表達(dá)式) -- 創(chuàng)建正則表達(dá)式對(duì)象
re_str = r'\d{3}'
re_obj = compile(re_str)
re_obj.fullmatch('234')
  1. fullmatch -- 完全匹配
fullmatch(正則表達(dá)式喂江,字符串)  --  讓正則和字符串完全匹配;匹配失敗返回None,匹配成功返回匹配對(duì)象

對(duì)整個(gè)字符串進(jìn)行檢查的時(shí)候使用旁振,比如判斷賬號(hào)获询、密碼是否合法涨岁;手機(jī)號(hào)、郵箱是否合法等
result = fullmatch(r'\d{3}[a-z]{2}[A-Z]{3}', '234asGHD')
print(result)
  1. match -- 匹配字符串開(kāi)頭
match(正則表達(dá)式, 字符串)  --  讓正則和字符串開(kāi)頭匹配吉嚣;匹配失敗返回None梢薪,匹配成功返回匹配對(duì)象
result = match(r'\d{3}', '3495hsjs02-3')
print(result)
  1. search -- 字符串查找
search(正則表達(dá)式, 字符串)  --  在字符串中找到第一個(gè)和正則表達(dá)式匹配的子串;沒(méi)有匹配到就返回None尝哆,否則返回匹配對(duì)象
result = search(r'a(\d{3})([A-Z]{2})', 'a345AS')
print(result)   # <_sre.SRE_Match object; span=(0, 6), match='a345AS'>

通過(guò)匹配對(duì)象能獲取到以下內(nèi)容

# a.匹配結(jié)果
print(result.group())   # 獲取整個(gè)正則表達(dá)式匹配到的結(jié)果  a345AS
print(result.group(1))  # 獲取第一個(gè)分組匹配到的結(jié)果   345
print(result.group(2))  # 獲取第二個(gè)分組匹配到的結(jié)果   AS
# b.匹配返回(被匹配到的內(nèi)容在原字符串中的范圍-(開(kāi)始下標(biāo), 結(jié)束下標(biāo)))
print(result.span())    #  (0, 6)
print(result.start())    # 0
print(result.end())    # 6
# c.獲取原字符串
print(result.string)  # a345AS
  1. split -- 字符串切割
split(正則表達(dá)式, 字符串, 切割次數(shù))  --  將字符串按照滿足正則表達(dá)式的子串進(jìn)行切割秉撇;返回的是一個(gè)列表,列表中是被切開(kāi)的子串
切割次數(shù)  --  不傳參就全切
# ['alfhuiwe', 'h', 'ugy3fr23GHJFTY87GHJG8g6f']
print(split(r'\d+|[A-Z]+', 'alfhuiwe7384h2ugy3fr23GHJFTY87GHJG8g6f', 2))
  1. sub -- 字符串替換
sub(正則表達(dá)式,新字符串,原字符串,替換次數(shù))  --  將原字符串中滿足正則表達(dá)式的子串替換成新字符串
替換次數(shù)  --  不傳參就全部替換
print(sub(r'\d+', '*','aaisafyr34359yh47fus7srer98'))     # aaisafyr*yh*fus*srer*
  1. findall -- 查找所有
findall(正則表達(dá)式秋泄,字符串)  --  在字符串中查找所有滿足正則表達(dá)式的子串琐馆,以列表的形式返回
# 有一個(gè)分組,只取分組匹配到的內(nèi)容
print(findall(r'\d+a', 'afu78efha6asajf78fiwe98aeu3od'))  # ['6a', '98a']
# 有一個(gè)分組恒序,只取分組匹配到的內(nèi)容
print(findall(r'(\d+)a', 'afu78efha6asajf78fiwe98aeu3od'))    # ['6', '98']
print(findall(r'(\d+)([a-z]{2})', 'afu78efha6asajf78fiwe98aeu3od'))  # [('78', 'ef'), ('6', 'as'), ('78', 'fi'), ('98', 'ae'), ('3', 'od')]

注意:使用findall的時(shí)候瘦麸,如果有分組想要取整個(gè)正則匹配的結(jié)果是取不到的

print(findall(r'(\d[a-z]){3}\+', ''))   # []
  1. finditer -- 查找所有
finditer(正則表達(dá)式, 字符串)  --  在字符串中查找所有滿足正則表達(dá)式的子串:返回一個(gè)迭代器,元素是每個(gè)子串對(duì)應(yīng)的匹配結(jié)對(duì)象
result = finditer(r'(\d[a-z]){3}\+', 'ahjs8a2a8j+胡士大夫9m2s0j+接收到sd8p+ss===')
print(result)   # <callable_iterator object at 0x0056E190>
for x in result:
    print(x.group(), x.group(1))    # 8a2a8j+ 8j     9m2s0j+ 0j


教師資料-字符串和正則表達(dá)式

使用正則表達(dá)式

正則表達(dá)式相關(guān)知識(shí)

在編寫處理字符串的程序或網(wǎng)頁(yè)時(shí)歧胁,經(jīng)常會(huì)有查找符合某些復(fù)雜規(guī)則的字符串的需要滋饲,正則表達(dá)式就是用于描述這些規(guī)則的工具,換句話說(shuō)正則表達(dá)式是一種工具喊巍,它定義了字符串的匹配模式(如何檢查一個(gè)字符串是否有跟某種模式匹配的部分或者從一個(gè)字符串中將與模式匹配的部分提取出來(lái)或者替換掉)屠缭。如果你在Windows操作系統(tǒng)中使用過(guò)文件查找并且在指定文件名時(shí)使用過(guò)通配符(*和?),那么正則表達(dá)式也是與之類似的用來(lái)進(jìn)行文本匹配的工具崭参,只不過(guò)比起通配符正則表達(dá)式更強(qiáng)大呵曹,它能更精確地描述你的需求(當(dāng)然你付出的代價(jià)是書寫一個(gè)正則表達(dá)式比打出一個(gè)通配符要復(fù)雜得多,要知道任何給你帶來(lái)好處的東西都是有代價(jià)的阵翎,就如同學(xué)習(xí)一門編程語(yǔ)言一樣)逢并,比如你可以編寫一個(gè)正則表達(dá)式,用來(lái)查找所有以0開(kāi)頭郭卫,后面跟著2-3個(gè)數(shù)字砍聊,然后是一個(gè)連字號(hào)“-”,最后是7或8位數(shù)字的字符串(像028-12345678或0813-7654321)贰军,這不就是國(guó)內(nèi)的座機(jī)號(hào)碼嗎玻蝌。最初計(jì)算機(jī)是為了做數(shù)學(xué)運(yùn)算而誕生的,處理的信息基本上都是數(shù)值词疼,而今天我們?cè)谌粘9ぷ髦刑幚淼男畔⒒旧隙际俏谋緮?shù)據(jù)俯树,我們希望計(jì)算機(jī)能夠識(shí)別和處理符合某些模式的文本,正則表達(dá)式就顯得非常重要了贰盗。今天幾乎所有的編程語(yǔ)言都提供了對(duì)正則表達(dá)式操作的支持许饿,Python通過(guò)標(biāo)準(zhǔn)庫(kù)中的re模塊來(lái)支持正則表達(dá)式操作。

我們可以考慮下面一個(gè)問(wèn)題:我們從某個(gè)地方(可能是一個(gè)文本文件舵盈,也可能是網(wǎng)絡(luò)上的一則新聞)獲得了一個(gè)字符串陋率,希望在字符串中找出手機(jī)號(hào)和座機(jī)號(hào)球化。當(dāng)然我們可以設(shè)定手機(jī)號(hào)是11位的數(shù)字(注意并不是隨機(jī)的11位數(shù)字,因?yàn)槟銢](méi)有見(jiàn)過(guò)“25012345678”這樣的手機(jī)號(hào)吧)而座機(jī)號(hào)跟上一段中描述的模式相同瓦糟,如果不使用正則表達(dá)式要完成這個(gè)任務(wù)就會(huì)很麻煩筒愚。

關(guān)于正則表達(dá)式的相關(guān)知識(shí),大家可以閱讀一篇非常有名的博客叫《正則表達(dá)式30分鐘入門教程》菩浙,讀完這篇文章后你就可以看懂下面的表格巢掺,這是我們對(duì)正則表達(dá)式中的一些基本符號(hào)進(jìn)行的扼要總結(jié)。

符號(hào) 解釋 示例 說(shuō)明
. 匹配任意字符 b.t 可以匹配bat / but / b#t / b1t等
\w 匹配字母/數(shù)字/下劃線 b\wt 可以匹配bat / b1t / b_t等
但不能匹配b#t
\s 匹配空白字符(包括\r劲蜻、\n陆淀、\t等) love\syou 可以匹配love you
\d 匹配數(shù)字 \d\d 可以匹配01 / 23 / 99等
\b 匹配單詞的邊界 \bThe\b
^ 匹配字符串的開(kāi)始 ^The 可以匹配The開(kāi)頭的字符串
$ 匹配字符串的結(jié)束 .exe$ 可以匹配.exe結(jié)尾的字符串
\W 匹配非字母/數(shù)字/下劃線 b\Wt 可以匹配b#t / b@t等
但不能匹配but / b1t / b_t等
\S 匹配非空白字符 love\Syou 可以匹配love#you等
但不能匹配love you
\D 匹配非數(shù)字 \d\D 可以匹配9a / 3# / 0F等
\B 匹配非單詞邊界 \Bio\B
[] 匹配來(lái)自字符集的任意單一字符 [aeiou] 可以匹配任一元音字母字符
[^] 匹配不在字符集中的任意單一字符 [^aeiou] 可以匹配任一非元音字母字符
* 匹配0次或多次 \w*
+ 匹配1次或多次 \w+
? 匹配0次或1次 \w?
{N} 匹配N次 \w{3}
{M,} 匹配至少M(fèi)次 \w{3,}
{M,N} 匹配至少M(fèi)次至多N次 \w{3,6}
| 分支 foo|bar 可以匹配foo或者bar
(?#) 注釋
(exp) 匹配exp并捕獲到自動(dòng)命名的組中
(?<name>exp) 匹配exp并捕獲到名為name的組中
(?:exp) 匹配exp但是不捕獲匹配的文本
(?=exp) 匹配exp前面的位置 \b\w+(?=ing) 可以匹配I'm dancing中的danc
(?<=exp) 匹配exp后面的位置 (?<=\bdanc)\w+\b 可以匹配I love dancing and reading中的第一個(gè)ing
(?!exp) 匹配后面不是exp的位置
(?<!exp) 匹配前面不是exp的位置
*? 重復(fù)任意次,但盡可能少重復(fù) a.*b
a.*?b
將正則表達(dá)式應(yīng)用于aabab斋竞,前者會(huì)匹配整個(gè)字符串a(chǎn)abab倔约,后者會(huì)匹配aab和ab兩個(gè)字符串
+? 重復(fù)1次或多次,但盡可能少重復(fù)
?? 重復(fù)0次或1次坝初,但盡可能少重復(fù)
{M,N}? 重復(fù)M到N次浸剩,但盡可能少重復(fù)
{M,}? 重復(fù)M次以上,但盡可能少重復(fù)

說(shuō)明:如果需要匹配的字符是正則表達(dá)式中的特殊字符鳄袍,那么可以使用\進(jìn)行轉(zhuǎn)義處理绢要,例如想匹配小數(shù)點(diǎn)可以寫成\.就可以了,因?yàn)橹苯訉?會(huì)匹配任意字符拗小;同理重罪,想匹配圓括號(hào)必須寫成\(和\),否則圓括號(hào)被視為正則表達(dá)式中的分組哀九。

Python對(duì)正則表達(dá)式的支持

Python提供了re模塊來(lái)支持正則表達(dá)式相關(guān)操作剿配,下面是re模塊中的核心函數(shù)。

函數(shù) 說(shuō)明
compile(pattern, flags=0) 編譯正則表達(dá)式返回正則表達(dá)式對(duì)象
match(pattern, string, flags=0) 用正則表達(dá)式匹配字符串 成功返回匹配對(duì)象 否則返回None
search(pattern, string, flags=0) 搜索字符串中第一次出現(xiàn)正則表達(dá)式的模式 成功返回匹配對(duì)象 否則返回None
split(pattern, string, maxsplit=0, flags=0) 用正則表達(dá)式指定的模式分隔符拆分字符串 返回列表
sub(pattern, repl, string, count=0, flags=0) 用指定的字符串替換原字符串中與正則表達(dá)式匹配的模式 可以用count指定替換的次數(shù)
fullmatch(pattern, string, flags=0) match函數(shù)的完全匹配(從字符串開(kāi)頭到結(jié)尾)版本
findall(pattern, string, flags=0) 查找字符串所有與正則表達(dá)式匹配的模式 返回字符串的列表
finditer(pattern, string, flags=0) 查找字符串所有與正則表達(dá)式匹配的模式 返回一個(gè)迭代器
purge() 清除隱式編譯的正則表達(dá)式的緩存
re.I / re.IGNORECASE 忽略大小寫匹配標(biāo)記
re.M / re.MULTILINE 多行匹配標(biāo)記

說(shuō)明:上面提到的re模塊中的這些函數(shù)阅束,實(shí)際開(kāi)發(fā)中也可以用正則表達(dá)式對(duì)象的方法替代對(duì)這些函數(shù)的使用呼胚,如果一個(gè)正則表達(dá)式需要重復(fù)的使用,那么先通過(guò)compile函數(shù)編譯正則表達(dá)式并創(chuàng)建出正則表達(dá)式對(duì)象無(wú)疑是更為明智的選擇息裸。

下面我們通過(guò)一系列的例子來(lái)告訴大家在Python中如何使用正則表達(dá)式蝇更。

例子1:驗(yàn)證輸入用戶名和QQ號(hào)是否有效并給出對(duì)應(yīng)的提示信息。

"""

驗(yàn)證輸入用戶名和QQ號(hào)是否有效并給出對(duì)應(yīng)的提示信息

要求:
用戶名必須由字母呼盆、數(shù)字或下劃線構(gòu)成且長(zhǎng)度在6~20個(gè)字符之間
QQ號(hào)是5~12的數(shù)字且首位不能為0

"""

import re


def main():
    username = input('請(qǐng)輸入用戶名: ')
    qq = input('請(qǐng)輸入QQ號(hào): ')
    # match函數(shù)的第一個(gè)參數(shù)是正則表達(dá)式字符串或正則表達(dá)式對(duì)象
    # 第二個(gè)參數(shù)是要跟正則表達(dá)式做匹配的字符串對(duì)象
    m1 = re.match(r'^[0-9a-zA-Z_]{6,20}$', username)
    if not m1:
        print('請(qǐng)輸入有效的用戶名.')
    m2 = re.match(r'^[1-9]\d{4,11}$', qq)
    if not m2:
        print('請(qǐng)輸入有效的QQ號(hào).')
    if m1 and m2:
        print('你輸入的信息是有效的!')


if __name__ == '__main__':
    main()

提示:上面在書寫正則表達(dá)式時(shí)使用了“原始字符串”的寫法(在字符串前面加上了r)年扩,所謂“原始字符串”就是字符串中的每個(gè)字符都是它原始的意義,說(shuō)得更直接一點(diǎn)就是字符串中沒(méi)有所謂的轉(zhuǎn)義字符啦访圃。因?yàn)檎齽t表達(dá)式中有很多元字符和需要進(jìn)行轉(zhuǎn)義的地方厨幻,如果不使用原始字符串就需要將反斜杠寫作\\,例如表示數(shù)字的\d得書寫成\\d,這樣不僅寫起來(lái)不方便况脆,閱讀的時(shí)候也會(huì)很吃力平绩。

例子2:從一段文字中提取出國(guó)內(nèi)手機(jī)號(hào)碼。

下面這張圖是截止到2017年底漠另,國(guó)內(nèi)三家運(yùn)營(yíng)商推出的手機(jī)號(hào)段。

import re


def main():
    # 創(chuàng)建正則表達(dá)式對(duì)象 使用了前瞻和回顧來(lái)保證手機(jī)號(hào)前后不應(yīng)該出現(xiàn)數(shù)字
    pattern = re.compile(r'(?<=\D)1[34578]\d{9}(?=\D)')
    sentence = '''
    重要的事情說(shuō)8130123456789遍跃赚,我的手機(jī)號(hào)是13512346789這個(gè)靚號(hào)笆搓,
    不是15600998765,也是110或119纬傲,王大錘的手機(jī)號(hào)才是15600998765满败。
    '''
    # 查找所有匹配并保存到一個(gè)列表中
    mylist = re.findall(pattern, sentence)
    print(mylist)
    print('--------華麗的分隔線--------')
    # 通過(guò)迭代器取出匹配對(duì)象并獲得匹配的內(nèi)容
    for temp in pattern.finditer(sentence):
        print(temp.group())
    print('--------華麗的分隔線--------')
    # 通過(guò)search函數(shù)指定搜索位置找出所有匹配
    m = pattern.search(sentence)
    while m:
        print(m.group())
        m = pattern.search(sentence, m.end())


if __name__ == '__main__':
    main()

說(shuō)明:上面匹配國(guó)內(nèi)手機(jī)號(hào)的正則表達(dá)式并不夠好,因?yàn)橄?4開(kāi)頭的號(hào)碼只有145或147叹括,而上面的正則表達(dá)式并沒(méi)有考慮這種情況,要匹配國(guó)內(nèi)手機(jī)號(hào),更好的正則表達(dá)式的寫法是:(?<=\D)(1[38]\d{9}|14[57]\d{8}|15[0-35-9]\d{8}|17[678]\d{8})(?=\D)懂昂,國(guó)內(nèi)最近好像有19和16開(kāi)頭的手機(jī)號(hào)了轩褐,但是這個(gè)暫時(shí)不在我們考慮之列。

例子3:替換字符串中的不良內(nèi)容

import re


def main():
    sentence = '你丫是傻叉嗎? 我操你大爺?shù)? Fuck you.'
    purified = re.sub('[操肏艸草曹]|fuck|shit|傻[比屄逼叉缺吊屌]|煞筆',
                      '*', sentence, flags=re.IGNORECASE)
    print(purified)  # 你丫是*嗎? 我*你大爺?shù)? * you.


if __name__ == '__main__':
    main()

說(shuō)明:re模塊的正則表達(dá)式相關(guān)函數(shù)中都有一個(gè)flags參數(shù)侠讯,它代表了正則表達(dá)式的匹配標(biāo)記挖藏,可以通過(guò)該標(biāo)記來(lái)指定匹配時(shí)是否忽略大小寫、是否進(jìn)行多行匹配厢漩、是否顯示調(diào)試信息等膜眠。如果需要為flags參數(shù)指定多個(gè)值,可以使用按位或運(yùn)算符進(jìn)行疊加溜嗜,如flags=re.I | re.M宵膨。

例子4:拆分長(zhǎng)字符串

import re


def main():
    poem = '窗前明月光,疑是地上霜炸宵。舉頭望明月辟躏,低頭思故鄉(xiāng)。'
    sentence_list = re.split(r'[焙压,鸿脓。, .]', poem)
    while '' in sentence_list:
        sentence_list.remove('')
    print(sentence_list)  # ['窗前明月光', '疑是地上霜', '舉頭望明月', '低頭思故鄉(xiāng)']


if __name__ == '__main__':
    main()

后話

如果要從事爬蟲類應(yīng)用的開(kāi)發(fā),那么正則表達(dá)式一定是一個(gè)非常好的助手涯曲,因?yàn)樗梢詭椭覀冄杆俚膹木W(wǎng)頁(yè)代碼中發(fā)現(xiàn)某種我們指定的模式并提取出我們需要的信息野哭,當(dāng)然對(duì)于初學(xué)者來(lái)收,要編寫一個(gè)正確的適當(dāng)?shù)恼齽t表達(dá)式可能并不是一件容易的事情(當(dāng)然有些常用的正則表達(dá)式可以直接在網(wǎng)上找找)幻件,所以實(shí)際開(kāi)發(fā)爬蟲應(yīng)用的時(shí)候拨黔,有很多人會(huì)選擇Beautiful SoupLxml來(lái)進(jìn)行匹配和信息的提取,前者簡(jiǎn)單方便但是性能較差绰沥,后者既好用性能也好篱蝇,但是安裝稍嫌麻煩贺待,這些內(nèi)容我們會(huì)在后期的爬蟲專題中為大家介紹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末零截,一起剝皮案震驚了整個(gè)濱河市麸塞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涧衙,老刑警劉巖哪工,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弧哎,居然都是意外死亡雁比,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門撤嫩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)偎捎,“玉大人,你說(shuō)我怎么就攤上這事序攘≤钏” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵程奠,是天一觀的道長(zhǎng)败京。 經(jīng)常有香客問(wèn)我,道長(zhǎng)梦染,這世上最難降的妖魔是什么赡麦? 我笑而不...
    開(kāi)封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮帕识,結(jié)果婚禮上泛粹,老公的妹妹穿的比我還像新娘。我一直安慰自己肮疗,他們只是感情好晶姊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著伪货,像睡著了一般们衙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碱呼,一...
    開(kāi)封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天蒙挑,我揣著相機(jī)與錄音,去河邊找鬼愚臀。 笑死忆蚀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播馋袜,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼男旗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了欣鳖?” 一聲冷哼從身側(cè)響起察皇,我...
    開(kāi)封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泽台,沒(méi)想到半個(gè)月后让网,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡师痕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了而账。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胰坟。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泞辐,靈堂內(nèi)的尸體忽然破棺而出笔横,到底是詐尸還是另有隱情,我是刑警寧澤咐吼,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布吹缔,位于F島的核電站,受9級(jí)特大地震影響锯茄,放射性物質(zhì)發(fā)生泄漏厢塘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一肌幽、第九天 我趴在偏房一處隱蔽的房頂上張望晚碾。 院中可真熱鬧,春花似錦喂急、人聲如沸格嘁。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)糕簿。三九已至,卻和暖如春狡孔,著一層夾襖步出監(jiān)牢的瞬間懂诗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工苗膝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留响禽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像芋类,于是被迫代替她去往敵國(guó)和親隆嗅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容