Python正則表達(dá)式的應(yīng)用詳解
正則表達(dá)式的定義
在編寫(xiě)處理字符串的程時(shí),經(jīng)常會(huì)遇到在一段文本中查找符合某些規(guī)則的字符串的需求,正則表達(dá)式就是用于描述這些規(guī)則的工具,換句話(huà)說(shuō),我們可以使用正則表達(dá)式來(lái)定義字符串的匹配模式,即如何檢查一個(gè)字符串是否有跟某種模式匹配的部分或者從一個(gè)字符串中將與模式匹配的部分提取出來(lái)或者替換掉。
關(guān)于正則表達(dá)式的相關(guān)知識(shí),大家可以閱讀一篇非常有名的博文叫《正則表達(dá)式30分鐘入門(mén)教程》,讀完這篇文章后你就可以看懂下面的表格,這是我們對(duì)正則表達(dá)式中的一些基本符號(hào)進(jìn)行的扼要總結(jié)。
符號(hào) | 解釋 | 示例 | 說(shuō)明 |
---|---|---|---|
. | 匹配除換行符以外的任意字符 | b.t | 可以匹配bat / but / b#t / b1t等 |
\w | 匹配字母/數(shù)字/下劃線(xiàn)/漢字 | 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ù)字/下劃線(xiàn)/漢字 | 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(xiāo)次 | \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)可以寫(xiě)成\.就可以了,因?yàn)橹苯訉?xiě).會(huì)匹配任意字符;同理,想匹配圓括號(hào)必須寫(xiě)成\(和\),否則圓括號(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 | 忽略大小寫(xiě)匹配標(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ú)疑是更為明智的選擇。
示例
例1:驗(yàn)證輸入的用戶(hù)名是否有效,用戶(hù)名由長(zhǎng)度為6到20的字母、數(shù)字、下劃線(xiàn)組成
方法一:通過(guò)compile編譯正則表達(dá)式創(chuàng)建Pattern對(duì)象,通過(guò)給Pattern對(duì)象發(fā)消息實(shí)現(xiàn)匹配檢查。
import re username = input('請(qǐng)輸入用戶(hù)名:') # 通過(guò)compile編譯正則表達(dá)式創(chuàng)建Pattern對(duì)象 username_pattern = re.compile(r'^\w{6,20}$') print(type(username_pattern)) # 通過(guò)給Pattern對(duì)象發(fā)消息實(shí)現(xiàn)匹配檢查 matcher = username_pattern.match(username) print(type(matcher)) if matcher is None: print('無(wú)效的用戶(hù)名') else: print(matcher.group())
方法二:不創(chuàng)建正則表達(dá)式對(duì)象,直接調(diào)用函數(shù)進(jìn)行匹配操作
username = input('請(qǐng)輸入用戶(hù)名:') matcher = re.fullmatch(r'\w{6,20}', username) #^是開(kāi)始符,$是結(jié)束符 # matcher = re.match(r'^\w{6,20}$', username) if matcher is None: print('用戶(hù)名不合法!??!') else: print(matcher) print(matcher.group())
匹配操作可以使用match函數(shù),需要添加開(kāi)始符號(hào)^和結(jié)束符號(hào)$表示匹配字符串的開(kāi)始與結(jié)束;也可以使用fullmatch函數(shù),正則表達(dá)式不用寫(xiě)開(kāi)始符和結(jié)束符。上面在書(shū)寫(xiě)正則表達(dá)式時(shí)使用了“原始字符串”的寫(xiě)法。
例2:從字符串中找到與正則表達(dá)式匹配的部分
import re content = """報(bào)警電話(huà):110,我們班是Python-2105班, 我的QQ是9597658,我的手機(jī)號(hào)是13811223344,謝謝!""" searcher = re.search(r'1[3-9]\d{9}', content) if not searcher: print('沒(méi)有找到手機(jī)號(hào)') else: print(searcher.group())
匹配結(jié)果:
13811223344
import re content = """報(bào)警電話(huà):110,我們班是Python-2105班, 我的QQ是9597658,我的手機(jī)號(hào)是13811223344,謝謝!""" pattern = re.compile(r'\d+') matcher = pattern.search(content) while matcher: print(matcher.group()) # 從上一次匹配成功的結(jié)束位置開(kāi)始搜索 matcher = pattern.search(content, matcher.end())
匹配結(jié)果:
110
2105
9597658
13811223344
import re content = """報(bào)警電話(huà):110,我們班是Python-2105班, 我的QQ是9597658,我的手機(jī)號(hào)是13811223344,謝謝!""" pattern = re.compile(r'\d+') results = pattern.findall(content) # 沒(méi)有創(chuàng)建正則表達(dá)式對(duì)象時(shí),也可以用這種方法 # results = re.findall(r'\d+', content) for result in results: print(result)
匹配結(jié)果:
110
2105
9597658
13811223344
例3:從網(wǎng)頁(yè)上獲取新聞的標(biāo)題和鏈接
import re import requests resp = requests.get('https://www.sohu.com/') # .表示任意字符,+表示匹配一個(gè)或任意多個(gè),?表示惰性匹配,盡可能短的匹配 pattern = re.compile(r'href="http.+?"') # 拿到搜狐首頁(yè) content = resp.text matcher = pattern.search(content) while matcher: print(matcher.group()[6:-1]) matcher = pattern.search(content, matcher.end()) pattern2 = re.compile(r'title=".+?"') title_list = pattern2.findall(content) for title in title_list: print(title[7:-1])
對(duì)于例3,不能使新聞的標(biāo)題和鏈接對(duì)應(yīng)起來(lái),如果使用正則表達(dá)式捕獲組,可以實(shí)現(xiàn)標(biāo)題和鏈接的對(duì)應(yīng)。
import re import requests resp = requests.get('https://www.sohu.com/') # 匹配整個(gè)a標(biāo)簽,但是只捕獲()中的內(nèi)容 ---> 正則表達(dá)式的捕獲組 # .*連在一起就意味著任意數(shù)量的不包含換行的字符 pattern = re.compile(r'<a\s.*?href="(.+?)".*?title="(.+?)".*?>') content = resp.text results = pattern.findall(content) for href, title in results: print(title) if not href.startswith('https://www.sohu.com'): + href print(href)
例4:不良內(nèi)容過(guò)濾
import re content = '你真是一個(gè)沙雕煞筆,F(xiàn)uck you!' # pattern = re.compile(r'[傻沙煞][逼筆雕鄙]|馬化騰|fuck|shit', flags=re.IGNORECASE) # modified_content = pattern.sub('*', content) # print(modified_content) # |表示分支 modified_content = re.sub(r'[傻沙煞][逼筆雕鄙]|fuck|shit', '*', content, flags=re.I) print(modified_content)
例5:用正則表達(dá)式拆分字符串
import re poem = '床前明月光,疑是地上霜,舉頭望明月,低頭思故鄉(xiāng)。' # sentences_list = re.split(r'[,。]', poem) # sentences_list = re.split(r',|。', poem) pattern = re.compile(r'[,。]') sentences_list = pattern.split(poem) # sentences_list = [sentence for sentence in sentences_list if sentence] # print(sentences_list) for sentence in sentences_list: print(sentence)
運(yùn)行結(jié)果:
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉(xiāng)
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注本站的更多內(nèi)容!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。