前言:正則表達式在網(wǎng)絡(luò)爬蟲、數(shù)據(jù)分析中有著廣泛使用,掌握正則表達式能夠達到事半功倍的效果。本文詳細介紹正則表達式中各種規(guī)則及其符號含義,并結(jié)合Python中的Re庫進行演示,由淺入深,即學(xué)即練即用,內(nèi)容豐富,非常適合初學(xué)者。
正則表達式(regular expression)就是用一組由字母和符號組成的“表達式”來描述一個特征,然后去驗證另一個“字符串”是否符合這個特征。比如表達式“xy+” 描述的特征是“一個 ‘x’ 和 至少一個 ‘y'?”,那么‘xy',‘xyy', ‘xyyyyyyy'都符合這個特征。
正則表達式主要應(yīng)用場景
-
驗證字符串是否符合指定特征,比如驗證用戶名或密碼是否符合要求、是否是合法的郵件地址等;
-
用來查找字符串,從一個長的文本中查找符合指定特征的字符串,比查找固定字符串更加靈活方便;
-
用來替換,比普通的替換更強大。
正則表達式的規(guī)則
(1)普通字符
字母、數(shù)字、漢字、下劃線、以及沒有特殊定義的標(biāo)點符號,都是"普通字符"。表達式中的普通字符,在匹配一個字符串的時候,匹配與之相同的一個字符。
例1:表達式?“c”,在匹配字符串?“abcde”?時,匹配結(jié)果是:成功;匹配到的內(nèi)容是:“c”;匹配到的位置是:開始于2,結(jié)束于3。(包含開始位置,不包含結(jié)束位置)
例2:表達式 "bcd",在匹配字符串"abcde"時,匹配結(jié)果是:成功;匹配到的內(nèi)容是:"bcd";匹配到的位置是:開始于1,結(jié)束于4。
(2)轉(zhuǎn)義字符
-
一些不便書寫的字符,采用在前面加“\” 的方法。例如制表符、換行符等;
-
一些有特殊用處的標(biāo)點符號,在前面加“\” 后,代表該符號本身。例如{,}, [, ], /, \, +, *, ., $, ^, |, ??等;
轉(zhuǎn)義字符的匹配方法與“普通字符”類似,也是匹配與之相同的一個字符。
例如:表達式?"\$d",在匹配字符串?"abc$de"?時,匹配結(jié)果是:成功;匹配到的內(nèi)容是:"$d";匹配到的位置是:開始于3,結(jié)束于5。
(3)能夠與 '多種字符' 匹配的表達式
正則表達式中的一些表示方法,可以匹配 ‘多種字符’ 中的任意一個字符。例如,表達式"\d" 可以匹配任意一個數(shù)字。雖然可以匹配其中任意字符,但是只能是一個,不是多個。
例如:表達式?"\d\d",在匹配?"abc123"?時,匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"12";匹配到的位置是:開始于3,結(jié)束于5。
(4)自定義能夠匹配 '多種字符' 的表達式
使用方括號 [ ] 包含一系列字符,能匹配其中任意一個字符。用 [^ ] 包含一系列字符,則能匹配其中字符之外的任意一個字符。雖然可以匹配其中任意一個,但是只能是一個,不是多個。
例如:表達式?"[bcd][bcd]"?匹配?"abc123"?時,匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"bc";匹配到的位置是:開始于1,結(jié)束于3。
(5)修飾匹配次數(shù)的特殊符號
例如:表達式?"\d+\.?\d*"?在匹配?"It?costs?$12.5"?時,匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"12.5";匹配到的位置是:開始于10,結(jié)束于14。
(6)一些代表抽象意義的特殊符號
例1:表達式?"^aaa"?在匹配?"xxxaaaxxx"?時,匹配失敗。因為?"^"?要求與字符串開始的地方匹配,只有當(dāng)?"aaa"?位于字符串的開頭的時候,"^aaa"?才能匹配,比如:"aaaxxxxxx"。
例2:表達式 "aaa$"在匹配 "xxxaaaxxx" 時,匹配失敗。因為"$" 要求與字符串結(jié)束的地方匹配,只有當(dāng)"aaa"位于字符串的結(jié)尾的時候,"aaa$"才能匹配,比如:"xxxxxxaaa"。
例3:表達式?"Tom|Jack"在匹配字符串?"I'mTom, he is Jack"?時,匹配結(jié)果是:成功;匹配到的內(nèi)容是:"Tom";匹配到的位置是:開始于4,結(jié)束于7。匹配下一個時,匹配結(jié)果是:成功;匹配到的內(nèi)容是:"Jack";匹配到的位置時:開始于15,結(jié)束于19。
例4:表達式?"(go\s*)+"在匹配?"Let'sgo?gogo!"時,匹配結(jié)果是:成功;匹配到內(nèi)容是:"gogogo";匹配到的位置是:開始于6,結(jié)束于14。
例5:表達式?"¥(\d+\.?\d*)"在匹配?"$10.9,¥20.5"時,匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"¥20.5";匹配到的位置是:開始于6,結(jié)束于10。單獨獲取括號范圍匹配到的內(nèi)容是:"20.5"。
思考題:寫出滿足下列要求的正則表達式
-
僅含6位數(shù)字的字符串??
-
18位身份證號碼(最后一位可能包含X)
-
密碼(以字母開頭,長度在6~18之間,只能包含字母、數(shù)字和下劃線)
匹配次數(shù)中的貪婪與非貪婪
在使用修飾匹配次數(shù)的特殊符號時,如“?”,“*”, “+”等,可以使同一個表達式能夠匹配不同的次數(shù),具體匹配的次數(shù)隨被匹配的字符串而定。這種重復(fù)匹配不定次數(shù)的表達式在匹配過程中,總是盡可能多的匹配,這種匹配原則就叫作"貪婪" 模式?。例如,針對文本“dxxxdxxxd”,下列表達式匹配結(jié)果如下。
在修飾匹配次數(shù)的特殊符號后再加上一個"?" 號,則可以使匹配次數(shù)不定的表達式盡可能少的匹配,使可匹配可不匹配的表達式,盡可能的 "不匹配"。這種匹配原則叫作"非貪婪" 模式。如果少匹配就會導(dǎo)致整個表達式匹配失敗的時候,與貪婪模式類似,非貪婪模式會最小限度的再匹配一些,以使整個表達式匹配成功。例如,針對文本“dxxxdxxxd”,下列表達式匹配結(jié)果如下。
Python中的正則表達式庫 - re
-
re庫是Python的標(biāo)準庫,不需要額外安裝,主要用于字符串匹配
-
調(diào)用方式:import re
-
re 庫采用raw string類型表示正則表達式,rawstring是不包含對轉(zhuǎn)義符再次轉(zhuǎn)義的字符串。例如:r'[1‐9]\d{5}’
-
re庫也可以采用string類型表示正則表達式,但更繁瑣,例如“'[1‐9]\\d{5}'”
-
當(dāng)正則表達式包含轉(zhuǎn)義符時,建議使用raw string
re庫的主要功能函數(shù)
注意group()和groups()的區(qū)別,一個是返回匹配的字符串,一個是返回各部分匹配內(nèi)容組成的元組。當(dāng)表達式中沒有圓括號時,groups()返回的是空元組,當(dāng)存在圓括號時,有幾個圓括號groups()返回的元組里就有幾個元素。
正則表達式案例-驗證用戶名
編寫程序?qū)崿F(xiàn)下述功能,提示用戶輸入用戶名,要求用戶名以字母開頭,長度不少于3位,只能包含字母、數(shù)字、下劃線,如果用戶輸入符合要求,則提示注冊成功,否則提示用戶名不符合要求,請重新輸入,一直循環(huán)直到用戶名符合要求為止。程序執(zhí)行效果如下圖所示。
參考代碼如下:?
import re # 導(dǎo)入正則表達式庫
name = input("請輸入用戶名,以字母開頭,長度不少于3位,只能包含字母、數(shù)字、下劃線:") # 提示用戶輸入
match = re.match(r"^[a-zA-Z]\w{2,}$", name) # 驗證輸入是否符合要求
while match is None: # 如果不符合要求,則循環(huán)
print("用戶名不符合要求,請重新輸入:", end=" ") # 提示用戶名不符合要求
name = input() # 重新獲取用戶輸入
match = re.match(r"^[a-zA-Z]\w{2,}$", name) # 驗證輸入是否符合要求
print("恭喜你, {} ,注冊成功!".format(name)) # 提示注冊成功
思考:
- 正則表達式前面的^能夠省略?為什么?
- 有沒有其它等價的正則表達式寫法?
- 正則表達式最后的$能否省略?為什么?
正則表達式案例-編程語言排行
-
數(shù)據(jù)來源:https://www.tiobe.com/tiobe-index/網(wǎng)頁源代碼,保存到”編程語言排行.txt”文件。
-
部分內(nèi)容截圖如下,排行前十的編程語言數(shù)據(jù)存放在series屬性里,每項編程語言包含名稱(name)和數(shù)據(jù)(data)兩部分內(nèi)容,其中data部分包含該編程語言各個月份編程語言所占比例,。
import re # 正則表達式
import csv # csv文件操作
with open("編程語言排行.txt", mode="r", encoding="utf-8") as fp: # 打開指定文件
text = fp.read() # 讀取文件內(nèi)容
content = " ".join(re.findall(r"series: (.*?)\}\);", text, re.DOTALL)) # 獲取所有編程語言數(shù)據(jù)
total_content = re.findall(r"({.*?})", content, re.DOTALL) # 獲取各個編程語言的具體數(shù)據(jù)
with open("lang.csv", mode="w", encoding="utf-8", newline="") as fp: # 對數(shù)據(jù)進行處理并保存到文件
writer = csv.DictWriter(fp, ['name', 'value', 'date'])
writer.writeheader() # 寫入標(biāo)題
for item in total_content:
name = " ".join(re.findall(r"name : '(.*?)'", item, re.DOTALL))
temp_datas = re.findall(r"\[Date.UTC(.*?)\]", item, re.DOTALL) # 獲取不同時間的熱度信息
for data in temp_datas:
data = data.replace(" ", "").replace("(", "").replace(")", "")
value = data.split(",")[-1] # 熱度值
date = data.split(",")[:-1] # 日期信息
writer.writerow({"name": name, "value": value, "date": "{}-{:02d}-{:02d}".format(date[0], int(date[1]) + 1, int(date[2]))})
部分數(shù)據(jù)截圖效果如下:
文章來源:http://www.zghlxwxcb.cn/news/detail-437828.html
完整課件下載網(wǎng)址:https://download.csdn.net/download/Dream_Gao1989/81021441文章來源地址http://www.zghlxwxcb.cn/news/detail-437828.html
到了這里,關(guān)于詳解Python正則表達式(含豐富案例)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!