黑馬程序員Python45期講義筆記
在Python中需要通過正則表達(dá)式對(duì)字符串進(jìn)行匹配的時(shí)候踩麦,可以使用一個(gè) re 模塊
正則表達(dá)式的概述
1. 正則表達(dá)式的介紹
在實(shí)際開發(fā)過程中經(jīng)常會(huì)有查找符合某些復(fù)雜規(guī)則的字符串的需要作谭,比如:郵箱齐莲、圖片地址、手機(jī)號(hào)碼等,這時(shí)候想匹配或者查找符合某些規(guī)則的字符串就可以使用正則表達(dá)式了。
2. 正則表達(dá)式概念
正則表達(dá)式就是記錄文本規(guī)則的代碼
3. 正則表達(dá)式實(shí)例
0\d{2}-\d{8}
這個(gè)就是一個(gè)正則表達(dá)式,表達(dá)的意思是匹配的是座機(jī)號(hào)碼
4. 正則表達(dá)式的特點(diǎn)
- 正則表達(dá)式的語法很令人頭疼逻谦,可讀性差
- 正則表達(dá)式通用行很強(qiáng),能夠適用于很多編程語言
re模塊的介紹
首先要導(dǎo)入模塊:import re
match
方法進(jìn)行匹配操作用法:result = re.match(正則表達(dá)式,要匹配的字符串)
如果上一步匹配到數(shù)據(jù)的話奏属,可以使用group
方法來提取數(shù)據(jù):result.group()
### 導(dǎo)入re模塊
import re
### 使用match方法進(jìn)行匹配操作
result = re.match(正則表達(dá)式,要匹配的字符串)
### 如果上一步匹配到數(shù)據(jù)的話跨跨,可以使用group方法來提取數(shù)據(jù)
result.group()
rem模塊的使用
從字符串huangjing6344@novogene.com
中匹配出huangjing
:
import re
# 使用match方法進(jìn)行匹配操作
result = re.match("huangjing","huangjing6344@novogene.com")
# 獲取匹配結(jié)果
info = result.group()
print(info)
運(yùn)行結(jié)果:
huangjing
再來,如果我想從字符串huangjing6344@novogene.com
中匹配出novogene
就會(huì)報(bào)錯(cuò):
import re
# 使用match方法進(jìn)行匹配操作
result = re.match("novogene","huangjing6344@novogene.com")
# 獲取匹配結(jié)果
info = result.group()
print(info)
報(bào)錯(cuò)結(jié)果:
Traceback (most recent call last):
File "C:/Users/huangjing00liang/Desktop/練習(xí).py", line 6, in <module>
info = result.group()
AttributeError: 'NoneType' object has no attribute 'group'
為什么呀囱皿?匹配出huangjing
和novogene
按說是一個(gè)道理呀勇婴?
因?yàn)?re.match()
根據(jù)正則表達(dá)式從頭開始匹配字符串?dāng)?shù)據(jù)
錯(cuò)誤分析:
屬性錯(cuò)誤:'NoneType' 對(duì)象沒有屬性 'group'
說明由re.match()
函數(shù)返回給變量match
的是一個(gè)空的類型,所以在調(diào)用group()
方法時(shí)會(huì)報(bào)錯(cuò)嘱腥。
為什么會(huì)返回一個(gè)空變量呢耕渴?
是因?yàn)檫@個(gè)函數(shù)是從一個(gè)字符串的開始位置匹配正則表達(dá)式,然而這個(gè)字符串的起始位置并不符合正則表達(dá)式齿兔,所以匹配失敗橱脸,返回一個(gè)空變量,空變量并沒有group()
方法分苇,所以調(diào)用不成功添诉。
匹配單個(gè)字符
示例1:\d — 匹配一個(gè)數(shù)字,即0-9
我想找到這句話Total number of C's analysed: 27474733
里面的數(shù)字
"\d+"匹配多個(gè)數(shù)字:
import re
ret = re.search(r"\d+","Total number of C's analysed: 27474733")
print(ret.group())
運(yùn)行結(jié)果:
27474733
"\d"匹配一個(gè)數(shù)字:
import re
ret = re.search("\d","Total number of C's analysed: 27474733")
print(ret.group())
運(yùn)行結(jié)果:
2
體會(huì)下"\d"
和 "\d+"
的區(qū)別
示例2:. — 匹配任意1個(gè)字符(除了\n)
注意:是一個(gè)哦
import re
ret = re.match(".","raw_data")
print(ret.group())
ret = re.match("raw.","raw_data")
print(ret.group())
ret = re.match("raw_.","raw_data")
print(ret.group())
運(yùn)行結(jié)果:
r
raw_
raw_d
示例3:[] — 匹配[ ]中列舉的1個(gè)字符
如果hello的首字符小寫医寿,那么正則表達(dá)式需要小寫的h:
import re
ret = re.match("h","hello Python")
print(ret.group())
運(yùn)行結(jié)果:
h
如果hello的首字符大寫栏赴,那么正則表達(dá)式需要大寫的H:
import re
ret = re.match("H","Hello Python")
print(ret.group())
運(yùn)行結(jié)果:
H
使用[]匹配大小寫h都可以:
import re
ret = re.match("[hH]","hello Python")
print(ret.group())
ret = re.match("[hH]","Hello Python")
print(ret.group())
ret = re.match("[hH]ello Python","Hello Python")
print(ret.group())
運(yùn)行結(jié)果:
h
H
Hello Python
匹配0到9另一種寫法:
import re
ret = re.search("[0123456789]+","huangjing6344@novogene.com")
print(ret.group())
運(yùn)行結(jié)果:
6344
匹配0到9另一種寫法:
import re
ret = re.search("[0-9]","huangjing6344@novogene.com")
print(ret.group())
ret = re.search("[0-9]+","huangjing6344@novogene.com")
print(ret.group())
運(yùn)行結(jié)果:
6
6344
下面這個(gè)正則不能夠匹配到數(shù)字4:
import re
ret = re.search("[0-35-9]+","huangjing6344@novogene.com")
print(ret.group())
運(yùn)行結(jié)果:
63
示例4:\D — 表示匹配一個(gè)非數(shù)字,即不是數(shù)字
注意"\D"和"\D+"的區(qū)別:
import re
match_obj = re.match("\D", "huangjing6344@novogene.com")
print(match_obj.group())
match_obj = re.match("\D+", "huangjing6344@novogene.com")
print(match_obj.group())
運(yùn)行結(jié)果:
h
huangjing
示例5:\s — 匹配一個(gè)空白字符靖秩,即空格和tab鍵
空格屬于空白字符:
import re
match_obj = re.match("hello\sworld", "hello world")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失敗")
運(yùn)行結(jié)果:
hello world
\t
也屬于空白字符:
import re
match_obj = re.match("hello\sworld", "hello world")
if match_obj:
result = match_obj.group()
print(result)
else:
print("匹配失敗")
運(yùn)行結(jié)果:
hello world
示例6:\S — 匹配一個(gè)非空白
import re
match_obj = re.search("\S", "hello&world")
print(match_obj.group())
match_obj = re.search("hello\Sworld", "hello&world")
print(match_obj.group())
運(yùn)行結(jié)果:
h
hello&world
示例7:\w — 匹配一個(gè)非特殊字符须眷,即a-z、A-Z沟突、0-9花颗、_、漢字
import re
# 匹配非特殊字符中的一位
match_obj = re.match("\w", "huangjing6344@novogene.com")
print(match_obj.group())
# 匹配非特殊字符中的多位
match_obj = re.match("\w+", "huangjing6344@novogene.com")
print(match_obj.group())
運(yùn)行結(jié)果:
h
huangjing6344
示例8:\W — 匹配一個(gè)特殊字符惠拭,即非字母扩劝、非數(shù)字、非漢字
import re
match_obj = re.search("\W", "huangjing6344@novogene.com")
print(match_obj.group())
運(yùn)行結(jié)果:
@
注意這里使用re.match
會(huì)報(bào)錯(cuò)求橄,因?yàn)?code>huangjing6344@novogene.com中的特殊字符沒在開頭(如果是在開頭那使用re.match
和re.search
是一樣的效果):
import re
match_obj = re.match("\W", "huangjing6344@novogene.com")
print(match_obj.group())
報(bào)錯(cuò):
Traceback (most recent call last):
File "C:/Users/huangjing00liang/Desktop/練習(xí).py", line 5, in <module>
print(match_obj.group())
AttributeError: 'NoneType' object has no attribute 'group'
總結(jié):
-
.
表示匹配任意1個(gè)字符(除了\n) -
[ ]
表示匹配[ ]中列舉的1個(gè)字符 -
\d
表示匹配一個(gè)數(shù)字今野,即0-9 -
\D
表示匹配一個(gè)非數(shù)字,即不是數(shù)字 -
\s
表示匹配一個(gè)空白字符罐农,即 空格,tab鍵 -
\S
匹配一個(gè)非空白字符 -
\S
匹配一個(gè)非空白字符 -
\W
匹配一個(gè)特殊字符催什,即非字母涵亏、非數(shù)字、非漢字
匹配多個(gè)字符
示例1:* — 匹配前一個(gè)字符出現(xiàn)0次或者無限次,即可有可無
匹配出一個(gè)字符串第一個(gè)字母為大寫字符气筋,后面都是小寫字母并且這些小寫字母可有可無:
import re
ret = re.match("[A-Z][a-z]*","Huangjing6344")
print(ret.group())
ret = re.match("[A-Z][a-z]*","HuangJing6344")
print(ret.group())
運(yùn)行結(jié)果:
Huangjing
Huang
匹配出一個(gè)字符串開頭的大寫字母:
import re
ret = re.match("[A-Z]*","Huangjing6344")
print(ret.group())
ret = re.match("[A-Z]*","HJing6344")
print(ret.group())
運(yùn)行結(jié)果:
H
HJ
示例2:+ — 匹配前一個(gè)字符出現(xiàn)1次或者無限次拆内,即至少有1次
匹配一個(gè)字符串,第一個(gè)字符是h宠默,最后一個(gè)字符串是g麸恍,中間至少有一個(gè)字符:
import re
ret = re.match("h.+g","huangjing6344")
print(ret.group())
運(yùn)行結(jié)果:
huangjing
示例3:? — 匹配前一個(gè)字符出現(xiàn)1次或者0次,即要么有1次搀矫,要么沒有
匹配出這樣的數(shù)據(jù)抹沪,但是https 這個(gè)s可能有,也可能是http 這個(gè)s沒有
import re
ret = re.match("https?", "http")
print(ret.group())
ret = re.match("https?", "https")
print(ret.group())
運(yùn)行結(jié)果:
http
https
示例4:{m}瓤球、{m,n}
- {m}表示匹配前一個(gè)字符出現(xiàn)m次
- {m,n}表示匹配前一個(gè)字符出現(xiàn)從m到n次
import re
ret = re.match("[a-zA-Z0-9_]{8}","huang00jing")
print(ret.group())
ret = re.match("[a-zA-Z0-9_]{5,8}","huang00jing")
print(ret.group())
運(yùn)行結(jié)果:
huang
huang00j
總結(jié):
-
*
表示匹配前一個(gè)字符出現(xiàn)0次或者無限次融欧,即可有可無 -
+
表示匹配前一個(gè)字符出現(xiàn)1次或者無限次,即至少有1次 -
?
表示匹配前一個(gè)字符出現(xiàn)1次或者0次卦羡,即要么有1次噪馏,要么沒有 -
{m}
表示匹配前一個(gè)字符出現(xiàn)m次 -
{m,n}
表示匹配前一個(gè)字符出現(xiàn)從m到n次
匹配開頭和結(jié)尾
示例1:^ — 匹配字符串開頭
需求:匹配以數(shù)字開頭的數(shù)據(jù)
import re
# 匹配以數(shù)字開頭的數(shù)據(jù)
match_obj = re.match("^\d.*", "1.QC_Methy")
if match_obj:
# 獲取匹配結(jié)果
print(match_obj.group())
else:
print("匹配失敗")
運(yùn)行結(jié)果:
1.QC_Methy
示例2:$ — 匹配字符串結(jié)尾
需求: 匹配以數(shù)字結(jié)尾的數(shù)據(jù)
import re
# 匹配以數(shù)字結(jié)尾的數(shù)據(jù)
match_obj = re.match(".*\d$", "huangjing6344")
if match_obj:
# 獲取匹配結(jié)果
print(match_obj.group())
else:
print("匹配失敗")
運(yùn)行結(jié)果:
huangjing6344
示例3:^ 和 $
需求: 匹配以數(shù)字開頭中間內(nèi)容不管以數(shù)字結(jié)尾
import re
match_obj = re.match("^\d.*\d$", "0.log_1")
if match_obj:
# 獲取匹配結(jié)果
print(match_obj.group())
else:
print("匹配失敗")
運(yùn)行結(jié)果:
0.log_1
除了指定字符以外都匹配
- [^指定字符]: 表示除了指定字符都匹配
- 例如:[^h]: 表示除了指定字符h以外都匹配
import re
match_obj = re.match("[^h]", "jing")
if match_obj:
# 獲取匹配結(jié)果
print(match_obj.group())
else:
print("匹配失敗")
運(yùn)行結(jié)果:
j
總結(jié):
-
^
表示匹配字符串開頭 -
$
表示匹配字符串結(jié)尾
匹配分組
示例1:| — 匹配左右任意一個(gè)表達(dá)式
需求:在列表中["apple", "banana", "orange", "pear"],匹配apple和pear
import re
# 水果列表
fruit_list = ["apple", "banana", "orange", "pear"]
# 遍歷數(shù)據(jù)
for value in fruit_list:
# | 匹配左右任意一個(gè)表達(dá)式
match_obj = re.match("apple|pear", value)
if match_obj:
print("%s是我想要的" % match_obj.group())
else:
print("%s不是我要的" % value)
運(yùn)行結(jié)果:
apple是我想要的
banana不是我要的
orange不是我要的
pear是我想要的
示例2:( ) — 將括號(hào)中字符作為一個(gè)分組
需求:匹配出163绿饵、126欠肾、qq等郵箱
import re
match_obj = re.match("[a-zA-Z0-9_]{4,20}@(163|126|qq|sina|yahoo)\.com", "hello@163.com")
if match_obj:
print(match_obj.group())
# 獲取分組數(shù)據(jù)
print(match_obj.group(1))
else:
print("匹配失敗")
運(yùn)行結(jié)果:
hello@163.com
163
需求: 匹配qq:10567這樣的數(shù)據(jù),提取出來qq文字和qq號(hào)碼
import re
match_obj = re.match("(qq):([1-9]\d{4,10})", "qq:10567")
if match_obj:
print(match_obj.group())
# 分組:默認(rèn)是1一個(gè)分組拟赊,多個(gè)分組從左到右依次加1
print(match_obj.group(1))
# 提取第二個(gè)分組數(shù)據(jù)
print(match_obj.group(2))
else:
print("匹配失敗")
運(yùn)行結(jié)果:
qq:10567
qq
10567
示例3:\num
— 引用分組num匹配到的字符串
需求:匹配出<html>hh</html>
import re
match_obj = re.match("<[a-zA-Z1-6]+>.*</[a-zA-Z1-6]+>", "<html>hh</div>")
if match_obj:
print(match_obj.group())
else:
print("匹配失敗")
###引用分組1匹配到的字符串
### 正則表達(dá)式中必須是兩個(gè)斜杠:\\1
match_obj = re.match("<([a-zA-Z1-6]+)>.*</\\1>", "<html>hh</html>")
if match_obj:
print(match_obj.group())
else:
print("匹配失敗")
示例4:(?P<name>) (?P=name)
— 引用別名為name分組匹配到的字符串
匹配出<html><h1>www.processon.com</h1></html>:
import re
match_obj = re.match("<(?P<name1>[a-zA-Z1-6]+)><(?P<name2>[a-zA-Z1-6]+)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.processon.com</h1></html>")
if match_obj:
print(match_obj.group())
else:
print("匹配失敗")
運(yùn)行結(jié)果:
<html><h1>www.processon.com</h1></html>
注意:
- 分組的數(shù)據(jù)是從左向右的方式進(jìn)行分配的
-
re.match
只匹配字符串的開始刺桃,如果字符串開始不符合正則表達(dá)式,則匹配失敗要门,函數(shù)返回None
虏肾;而re.search
匹配整個(gè)字符串,直到找到一個(gè)匹配欢搜。
總結(jié):
-
|
表示匹配左右任意一個(gè)表達(dá)式 -
(ab)
表示將括號(hào)中字符作為一個(gè)分組 -
\num
表示引用分組num匹配到的字符串 -
(?P<name>)
表示分組起別名 -
(?P=name)
表示引用別名為name分組匹配到的字符串 -
(分組數(shù)據(jù))
分組數(shù)是從左到右的方式進(jìn)行分配的封豪,最左邊的是第一個(gè)分組,依次類推