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'
为什么呀?匹配出huangjing
和novogene
按说是一个道理呀?
因为 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.match
和re.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分组匹配到的字符串 -
(分组数据)
分组数是从左到右的方式进行分配的,最左边的是第一个分组,依次类推