Python中re模块的介绍—正则表达式

黑马程序员Python45期讲义笔记

在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个 re 模块

正则表达式的概述

1. 正则表达式的介绍

在实际开发过程中经常会有查找符合某些复杂规则的字符串的需要,比如:邮箱、图片地址、手机号码等,这时候想匹配或者查找符合某些规则的字符串就可以使用正则表达式了。

2. 正则表达式概念

正则表达式就是记录文本规则的代码

3. 正则表达式实例

0\d{2}-\d{8} 这个就是一个正则表达式,表达的意思是匹配的是座机号码

4. 正则表达式的特点

  • 正则表达式的语法很令人头疼,可读性差
  • 正则表达式通用行很强,能够适用于很多编程语言

re模块的介绍

首先要导入模块:import re
match方法进行匹配操作用法:result = re.match(正则表达式,要匹配的字符串)
如果上一步匹配到数据的话,可以使用group方法来提取数据:result.group()

### 导入re模块
import re

### 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)

### 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()

rem模块的使用

从字符串huangjing6344@novogene.com中匹配出huangjing

import re

# 使用match方法进行匹配操作
result = re.match("huangjing","huangjing6344@novogene.com")
# 获取匹配结果
info = result.group()
print(info)

运行结果:

huangjing

再来,如果我想从字符串huangjing6344@novogene.com中匹配出novogene就会报错:

import re

# 使用match方法进行匹配操作
result = re.match("novogene","huangjing6344@novogene.com")
# 获取匹配结果
info = result.group()
print(info)

报错结果:

Traceback (most recent call last):
  File "C:/Users/huangjing00liang/Desktop/练习.py", line 6, in <module>
    info = result.group()
AttributeError: 'NoneType' object has no attribute 'group'

为什么呀?匹配出huangjingnovogene按说是一个道理呀?
因为 re.match() 根据正则表达式从头开始匹配字符串数据

错误分析:
属性错误:'NoneType' 对象没有属性 'group'
说明由re.match()函数返回给变量match的是一个空的类型,所以在调用group()方法时会报错。
为什么会返回一个空变量呢?
是因为这个函数是从一个字符串的开始位置匹配正则表达式,然而这个字符串的起始位置并不符合正则表达式,所以匹配失败,返回一个空变量,空变量并没有group()方法,所以调用不成功。

匹配单个字符

正则表达式的单字符匹配

示例1:\d — 匹配一个数字,即0-9

我想找到这句话Total number of C's analysed: 27474733里面的数字
"\d+"匹配多个数字:

import re

ret = re.search(r"\d+","Total number of C's analysed:   27474733")
print(ret.group())

运行结果:

27474733

"\d"匹配一个数字:

import re

ret = re.search("\d","Total number of C's analysed: 27474733")
print(ret.group())

运行结果:

2

体会下"\d""\d+" 的区别

示例2:. — 匹配任意1个字符(除了\n)

注意:是一个哦

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())

运行结果:

r
raw_
raw_d

示例3:[] — 匹配[ ]中列举的1个字符

如果hello的首字符小写,那么正则表达式需要小写的h:

import re

ret = re.match("h","hello Python")
print(ret.group())

运行结果:

h

如果hello的首字符大写,那么正则表达式需要大写的H:

import re

ret = re.match("H","Hello Python")
print(ret.group())

运行结果:

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())

运行结果:

h
H
Hello Python

匹配0到9另一种写法:

import re

ret = re.search("[0123456789]+","huangjing6344@novogene.com")
print(ret.group())

运行结果:

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())

运行结果:

6
6344

下面这个正则不能够匹配到数字4:

import re

ret = re.search("[0-35-9]+","huangjing6344@novogene.com")
print(ret.group())

运行结果:

63

示例4:\D — 表示匹配一个非数字,即不是数字

注意"\D"和"\D+"的区别:

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())

运行结果:

h
huangjing

示例5:\s — 匹配一个空白字符,即空格和tab键

空格属于空白字符:

import re

match_obj = re.match("hello\sworld", "hello world")
if match_obj:
    result = match_obj.group()
    print(result)
else:
    print("匹配失败")

运行结果:

hello world

\t也属于空白字符:

import re

match_obj = re.match("hello\sworld", "hello world")
if match_obj:
    result = match_obj.group()
    print(result)
else:
    print("匹配失败")

运行结果:

hello world

示例6:\S — 匹配一个非空白

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())

运行结果:

h
hello&world

示例7:\w — 匹配一个非特殊字符,即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())

运行结果:

h
huangjing6344

示例8:\W — 匹配一个特殊字符,即非字母、非数字、非汉字

import re

match_obj = re.search("\W", "huangjing6344@novogene.com")
print(match_obj.group())

运行结果:

@

注意这里使用re.match会报错,因为huangjing6344@novogene.com中的特殊字符没在开头(如果是在开头那使用re.matchre.search是一样的效果):

import re

match_obj = re.match("\W", "huangjing6344@novogene.com")
print(match_obj.group())

报错:

Traceback (most recent call last):
  File "C:/Users/huangjing00liang/Desktop/练习.py", line 5, in <module>
    print(match_obj.group())
AttributeError: 'NoneType' object has no attribute 'group'

总结:

  • . 表示匹配任意1个字符(除了\n)
  • [ ] 表示匹配[ ]中列举的1个字符
  • \d 表示匹配一个数字,即0-9
  • \D 表示匹配一个非数字,即不是数字
  • \s 表示匹配一个空白字符,即 空格,tab键
  • \S 匹配一个非空白字符
  • \S 匹配一个非空白字符
  • \W 匹配一个特殊字符,即非字母、非数字、非汉字

匹配多个字符

匹配多个字符

示例1:* — 匹配前一个字符出现0次或者无限次,即可有可无

匹配出一个字符串第一个字母为大写字符,后面都是小写字母并且这些小写字母可有可无:

import re

ret = re.match("[A-Z][a-z]*","Huangjing6344")
print(ret.group())

ret = re.match("[A-Z][a-z]*","HuangJing6344")
print(ret.group())

运行结果:

Huangjing
Huang

匹配出一个字符串开头的大写字母:

import re

ret = re.match("[A-Z]*","Huangjing6344")
print(ret.group())

ret = re.match("[A-Z]*","HJing6344")
print(ret.group())

运行结果:

H
HJ

示例2:+ — 匹配前一个字符出现1次或者无限次,即至少有1次

匹配一个字符串,第一个字符是h,最后一个字符串是g,中间至少有一个字符:

import re

ret = re.match("h.+g","huangjing6344")
print(ret.group())

运行结果:

huangjing

示例3:? — 匹配前一个字符出现1次或者0次,即要么有1次,要么没有

匹配出这样的数据,但是https 这个s可能有,也可能是http 这个s没有

import re

ret = re.match("https?", "http")
print(ret.group())

ret = re.match("https?", "https")
print(ret.group())

运行结果:

http
https

示例4:{m}、{m,n}

  • {m}表示匹配前一个字符出现m次
  • {m,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())

运行结果:

huang
huang00j

总结:

  • * 表示匹配前一个字符出现0次或者无限次,即可有可无
  • + 表示匹配前一个字符出现1次或者无限次,即至少有1次
  • ? 表示匹配前一个字符出现1次或者0次,即要么有1次,要么没有
  • {m} 表示匹配前一个字符出现m次
  • {m,n} 表示匹配前一个字符出现从m到n次

匹配开头和结尾

匹配开头和结尾

示例1:^ — 匹配字符串开头

需求:匹配以数字开头的数据

import re

# 匹配以数字开头的数据
match_obj = re.match("^\d.*", "1.QC_Methy")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

1.QC_Methy

示例2:$ — 匹配字符串结尾

需求: 匹配以数字结尾的数据

import re
# 匹配以数字结尾的数据
match_obj = re.match(".*\d$", "huangjing6344")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

huangjing6344

示例3:^ 和 $

需求: 匹配以数字开头中间内容不管以数字结尾

import re
match_obj = re.match("^\d.*\d$", "0.log_1")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

0.log_1

除了指定字符以外都匹配

  • [^指定字符]: 表示除了指定字符都匹配
  • 例如:[^h]: 表示除了指定字符h以外都匹配
import re

match_obj = re.match("[^h]", "jing")
if match_obj:
    # 获取匹配结果
    print(match_obj.group())
else:
    print("匹配失败")

运行结果:

j

总结:

  • ^ 表示匹配字符串开头
  • $ 表示匹配字符串结尾

匹配分组

匹配分组相关正则表达式

示例1:| — 匹配左右任意一个表达式

需求:在列表中["apple", "banana", "orange", "pear"],匹配apple和pear

import re

# 水果列表
fruit_list = ["apple", "banana", "orange", "pear"]

# 遍历数据
for value in fruit_list:
    # |    匹配左右任意一个表达式
    match_obj = re.match("apple|pear", value)
    if match_obj:
        print("%s是我想要的" % match_obj.group())
    else:
        print("%s不是我要的" % value)

运行结果:

apple是我想要的
banana不是我要的
orange不是我要的
pear是我想要的

示例2:( ) — 将括号中字符作为一个分组

需求:匹配出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())
    # 获取分组数据
    print(match_obj.group(1))
else:
    print("匹配失败")

运行结果:

hello@163.com
163

需求: 匹配qq:10567这样的数据,提取出来qq文字和qq号码

import re

match_obj = re.match("(qq):([1-9]\d{4,10})", "qq:10567")

if match_obj:
    print(match_obj.group())
    # 分组:默认是1一个分组,多个分组从左到右依次加1
    print(match_obj.group(1))
    # 提取第二个分组数据
    print(match_obj.group(2))
else:
    print("匹配失败")

运行结果:

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匹配到的字符串
### 正则表达式中必须是两个斜杠:\\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("匹配失败")

运行结果:

<html><h1>www.processon.com</h1></html>

注意:

  • 分组的数据是从左向右的方式进行分配的
  • re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

总结:

  • | 表示匹配左右任意一个表达式
  • (ab) 表示将括号中字符作为一个分组
  • \num 表示引用分组num匹配到的字符串
  • (?P<name>) 表示分组起别名
  • (?P=name) 表示引用别名为name分组匹配到的字符串
  • (分组数据) 分组数是从左到右的方式进行分配的,最左边的是第一个分组,依次类推
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容