Python中re模塊的介紹—正則表達(dá)式

黑馬程序員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'

為什么呀囱皿?匹配出huangjingnovogene按說是一個(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è)字符

正則表達(dá)式的單字符匹配

示例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.matchre.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è)字符

匹配多個(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é)尾

匹配開頭和結(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é)尾

匹配分組

匹配分組相關(guān)正則表達(dá)式

示例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è)分組,依次類推
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炒瘟,一起剝皮案震驚了整個(gè)濱河市吹埠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疮装,老刑警劉巖缘琅,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異廓推,居然都是意外死亡刷袍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門樊展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呻纹,“玉大人堆生,你說我怎么就攤上這事±桌遥” “怎么了淑仆?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)哥力。 經(jīng)常有香客問我蔗怠,道長(zhǎng),這世上最難降的妖魔是什么吩跋? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任寞射,我火速辦了婚禮,結(jié)果婚禮上钞澳,老公的妹妹穿的比我還像新娘怠惶。我一直安慰自己,他們只是感情好轧粟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布策治。 她就那樣靜靜地躺著,像睡著了一般兰吟。 火紅的嫁衣襯著肌膚如雪通惫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天混蔼,我揣著相機(jī)與錄音履腋,去河邊找鬼。 笑死惭嚣,一個(gè)胖子當(dāng)著我的面吹牛遵湖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晚吞,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼延旧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了槽地?” 一聲冷哼從身側(cè)響起迁沫,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捌蚊,沒想到半個(gè)月后集畅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缅糟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年挺智,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗宦。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逃贝,死狀恐怖谣辞,靈堂內(nèi)的尸體忽然破棺而出迫摔,到底是詐尸還是另有隱情沐扳,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布句占,位于F島的核電站沪摄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纱烘。R本人自食惡果不足惜杨拐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望擂啥。 院中可真熱鬧哄陶,春花似錦、人聲如沸哺壶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山宾。三九已至至扰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間资锰,已是汗流浹背敢课。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绷杜,地道東北人直秆。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鞭盟,于是被迫代替她去往敵國(guó)和親圾结。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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