正则表达式
1.正则表达式的作用
正则表达式是对字符串操作的一种匹配公式
匹配或者查找符合某些规则的字符串就可以使用正则表达式
2.正则表达式的概念
1.正则表达式的概念
正则表达式就是记录文本规则的代码
2.正则表达式的样子
0\d{2}-\d{8}这个就是一个正则表达式,表达的意思是匹配的是座机号
3.正则表达式的特点
正则表达式的语法很令人头疼,可读性差
正则表达式通用性很强,能够适应于很多编程语言
3.re模块
在python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个re模块
1.使用流程:
1.导入re模块 import re
2.match匹配数据
match(“正则表达式”,“要匹配的字符”)
result = re.match(“正则表达式”,“要匹配的字符”)
3.group提取数据
result.group()
2.匹配单个字符
. :匹配任意1个字符(除了\n)
[]:匹配[]中列举的字符
\d:匹配数字,即0-9
\D:匹配非数字,不是0-9
\s:匹配空白,即空格,tab键
\S:匹配非空白
\w:匹配非特殊字符,即a-z,A-Z,0-9,_,汉字
\W:匹配特殊字符,即非字母,非数字,非汉字…
\A:仅匹配字符串开头,同^
\Z:仅匹配字符串结尾,同$
\b:匹配一个单词边界,也就单词和空格间的位置
实例:
. :匹配任意1个字符(除了\n)
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# . :匹配任意1个字符(除了\n)
result = re.match("xlz.", "xlz\n")
# result = re.match("xlz.", "xlz1")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
[]:匹配[]中列举的字符
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# []:匹配[]中列举的字符
# result = re.match("xlz[1234abc]", "xlza")
result = re.match("xlz[1234abc]", "xlz7")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\d:匹配数字,即0-9
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \d:匹配数字,即0-9 [0,1,2,3,4,5,6,7,8,9]
# result =re.match("xlz[0-9]",'xlz4')
result = re.match("xlz\d", "xlz1")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\D:匹配非数字,不是0-9
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \D:匹配非数字,不是0-9
result = re.match("xlz\D", "xlza")
# result = re.match("xlz\D", "xlz9")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\s:匹配空白,即空格,tab键
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \s:匹配空白,即空格,tab键
result = re.match("xlz\sxlz", "xlz xlz")
# result = re.match("xlz\sxlz", "xlz1xlz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\S:匹配非空白
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \S:匹配非空白
result = re.match("xlz\S", "xlz!")
# result = re.match("xlz\Sxlz", "xlz xlz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\w:匹配非特殊字符,即a-z,A-Z,0-9,_,汉字
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \w:匹配非特殊字符,即a-z,A-Z,0-9,_,汉字
result = re.match("xlz\w", "xlz廖")
# result = re.match("xlz\w", "xlz*")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
\W:匹配特殊字符,即非字母,非数字,非汉字…
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# \W:匹配特殊字符,即非字母,非数字,非汉字......
result = re.match("xlz\W", "xlz&")
# result = re.match("xlz\W", "xlz9")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
3.匹配多个字符
*:表示匹配前一个字符出现0次或者多次,即可有可无;
+:表示匹配前一个字符出现1次或者多次,即至少有1次;
?:表示匹配前一个字符出现1次,或者0次,即要么有1次,要么没有
{m}:表示匹配前一个字符出现m次
{m,n}:表示匹配前一个字符出现m到n次
实例:
*:表示匹配前一个字符出现0次或者多次,即可有可无;
# 导入re模块
import re
# 匹配多个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# *:表示匹配前一个字符出现0次或者多次,即可有可无;
# result = re.match("xlz*xlz","xlzzzxlz")
# result = re.match("xlz\d*xlz","xlz5zzxlz")
result = re.match("xlz*xlz","xlxlz")
# 获取数据# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
+:表示匹配前一个字符出现1次或者多次,即至少有1次;
# 导入re模块
import re
# 匹配多个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# +:表示匹配前一个字符出现1次或者多次,即至少有1次;
result = re.match("xlz\d+xlz","xlz123xlz")
# result = re.match("xlz\d+xlz","xlz1xlz")
# result = re.match("xlz\d+xlz","xlzxlz")
# 获取数据# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
?:表示匹配前一个字符出现1次,或者0次,即要么有1次,要么没有
# 导入re模块
import re
# 匹配多个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# ?:表示匹配前一个字符出现1次,或者0次,即要么有1次,要么没有
# result = re.match("xlz\d?xlz","xlz12345xlz")
# result = re.match("xlz\d?xlz","xlz7xlz")
result = re.match("xlz\d?xlz","xlzAxlz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
{m}:表示匹配前一个字符出现m次
# 导入re模块
import re
# 匹配多个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# {m}:表示匹配前一个字符出现m次
# result = re.match("xlz\d{3}xlz","xlz123xlz")
# result = re.match("xlz\d{3}xlz","xlz7xlz")
result = re.match("xlz\d{3}xlz","xlzAxlz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
{m,n}:表示匹配前一个字符出现m到n次
# 导入re模块
import re
# 匹配多个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# {m,n}:表示匹配前一个字符出现m到n次
# result = re.match("xlz\d{3,}xlz","xlz12334567xlz")
# result = re.match("xlz\d{3,5}xlz","xlz7467xlz")
result = re.match("xlz\d{3,5}xlz","xlzAxlz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
4.匹配开头和结尾
^:匹配字符串开头
# 导入re模块
import re
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# 匹配以数字为开头的字符串
# ^:匹配字符串开头
result = re.match("^\d.*","22345xlzzz")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
&:匹配字符串结尾
# 导入re模块
import re
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
# $:匹配字符串结尾
result = re.match(".*8$","2xlzzzz8")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
# 匹配以数字开头,以数字为结尾的的字符串
result = re.match("^\d.*\d$","12asdfgbghfds678"
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
[^指定字符]:匹配除了指定字符以外的所有字符
# 导入re模块
import re
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
result = re.match("^\d.*[^4]$","2xlzzz4")
# result = re.match("^\d.*[^4]$","2xlzzzd")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到字符")
5.匹配分组
|:匹配左右任意一个表达式
(ab):将括号中字符作为一个分组
\num:引用分组num匹配到的字符串
(?P):分组起别名
(?P=name):引用别名为name分组匹配到的字符串
案列:
-
在列表中[“apple”, “banana”, “orange”, “pear”],匹配apple和pear
# 导入re模块 import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # 在列表中["apple", "banana", "orange", "pear"],匹配apple和pear # |:匹配左右任意一个表达式 fruit = ["apple", "banana", "orange", "pear"] for value in fruit: result = re.match("apple|pear",value) # 判断匹配是否成功 if result: info = result.group() print("我爱吃的水果:", info) else: print("这不是我爱吃的水果")
-
匹配出163、126、qq等邮箱
# 导入re模块 import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # |:匹配左右任意一个表达式 # (a,b)将括号中字符作为一个分组 # \ 转义字符 result = re.match("[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com","hello@126.com") if result: info = result.group() print(info) else: print("没有匹配到字符")
-
匹配qq:10567这样的数据,提取出来qq文字和qq号码
# 导入re模块 import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # group()默认group(0)代表匹配所有数据 # group(1)代表第一组数据 # group(n)代表第n组数据 # (a,b)将括号中字符作为一个分组 result = re.match("(qq):([1-9]\d{4,11})","qq:10567") if result: info = result.group() print(info) info1 = result.group(1) print(info1) info2 = result.group(2) print(info2) else: print("没有匹配到字符")
-
匹配出<html>hh</html>
import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # \num:引用分组num匹配到的字符串 一定要记得转义 result = re.match("<([a-zA-Z1-6]{4})>.*</\\1>","<html>hh</html>") if result: info = result.group() print(info) else: print("没有匹配到字符")
-
匹配出<html><h1>www.xlz.cn</h1></html>
# 匹配出<html><h1>www.xlz.cn</h1></html> import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # \num:引用分组num匹配到的字符串 一定要记得转义 # 多个分组 result = re.match("<([a-zA-Z1-6]{4})><([a-zA-Z1-6]{2})>.*</\\2></\\1>","<html><h1>www.xlz.cn</h1></html>") if result: info = result.group() print(info) else: print("没有匹配到字符")
-
匹配出<html><h1>www.xlz.cn<h1></html>
import re # 匹配分组 # 匹配数据,匹配到结果返回结果,匹配不到结果返回None # \num:引用分组num匹配到的字符串 一定要记得转义 # 多个分组 result = re.match("<(?P<html>[a-zA-Z1-6]{4})><(?P<h1>[a-zA-Z1-6]{2})>.*</(?P=h1)></(?P=html)>","<html><h1>www.xlz.cn</h1></html>") if result: info = result.group() print(info) else: print("没有匹配到字符")
6.扩展
1.正则表达式:
正则表达式本身是一种小型的、高度专业化的编程语言,而在python中,通过内嵌集成re模块,程序员们可以直接调用来实现正则匹配。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行;
2.python中的贪婪和非贪婪?
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符;
在"*","?","+","{m,n}"后面加上?,可以使贪婪变成非贪婪
# 导入模块
import re
result = re.findall('#.*#', '#Xlz#xlz#xlz#', re.I)
# ['#xlz#xlz#xlz#'] 贪婪:尽可能多的字符
print(result)
result = re.findall('#.*?#', '#XLZ#XLZ#xlz#', re.I)
# ?要么一个,要么0个,如果有多个也只返回一个
# ['#xlz#', '#xlz#'] 加上?可以使贪婪变成非贪婪
print(result)
re 模块:
re 模块的函数方法:
1.group()函数
group() 或者group(0):获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来,有参取匹配到的第几个;
group(n):获取匹配到的第n组的结果
# 导入re模块
import re
result = re.match("(xlz)(z.*)","xlzzz")
# 获取数据
if result:
# 打印匹配到的所有结果
info = result.group(0)
print(info)
# 打印到匹配的第1组的结果
info = result.group(1)
print(info)
# 打印到匹配的第2组的结果
info = result.group(2)
print(info)
else:
print("没有匹配到字符")
groups():获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果;
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
result = re.match("(xlz)\d{3,}(xlz)","xlz12334567xlz")
# 获取数据
if result:
# 以元组的方式拿出所有的分组结果
info = result.groups()
# ('xlz', 'xlz')
print(info)
else:
print("没有匹配到字符")
groupdict(): 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果;
# 导入re模块
import re
# 匹配单个字符
# 匹配数据,匹配到结果返回结果,匹配不到结果返回None
result = re.match("(?P<name>\D{3}).(?P<age>\d{2})","xlz,18")
# 获取数据
if result:
# 只拿出匹配到的字符串中分组部分定义了key的组结果
info = result.groupdict()
# {'name': 'xlz', 'age': '18'}
print(info)
else:
print("没有匹配到字符")
2.match()函数(以后常用)
match():从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
match(pattern, string, flags=0)
pattern: 正则模型
string : 要匹配的字符串
falgs : 匹配模式
# 导入模块
import re
# 从头(起始位置)匹配一个符合规则的字符串,匹配成功会返回一个对象
# 返回的对象可以使用group方法获取匹配到的数据,匹配不成功会返回空值
# 返回空值,用group方法获取会产生异常,所以我们会用一个条件判断来避免异常
# result = re.match("xlz,\d{2}","xzxlz,18")
result = re.match("xlz,\d{2}","xlz,18")
if result:
print(result)
info = result.group()
print(info)
else:
print("没有匹配到数据")
3.search()函数
浏览全部字符串,匹配第一符合规则的字符串,浏览整个字符串去匹配第一个,未匹配成功返回None
search(pattern, string, flags=0)
pattern: 正则模型
string : 要匹配的字符串
falgs:匹配模式
注意:match()函数 与 search()函数基本是一样的功能,不一样的就是match()匹配字符串开始位置的一个符合规则的字符串,search()是在字符串全局匹配第一个合规则的字符串
# 导入模块
import re
# 和match基本一样,不一样的是
# match()匹配字符串开始位置的一个符合规则的字符串
# search()是在字符串全局匹配第一个合规则的字符串
result = re.search("xlz","ilovexlz")
# result = re.search("xlz","ilovepython")
if result:
print(result)
info = result.group()
print(info)
else:
print("没有匹配到数据")
4.findall()函数(以后常用)
findall(pattern, string, flags=0)
pattern: 正则模型
string : 要匹配的字符串
falgs : 匹配模式
浏览全部字符串,匹配所有合规则的字符串,匹配到的字符串放到一个列表中,未匹配成功返回空列表
注意:一旦匹配成,再次匹配,是从前一次匹配成功的,后面一位开始的,也可以理解为匹配成功的字符串,不在参与下次匹配
# 导入模块
import re
# 浏览全部的字符串,匹配所有符合正则表达式的数据,匹配到结果以列表返回结果,匹配不到结果返回[]
# ['xlz,18']
result = re.findall("xlz,\d{2}","xlz,18")
# []
# result = re.findall("xlz,\d{2}","xlz,asdf")
print(result)
5.split()函数
根据正则匹配分割字符串,返回分割后的一个列表
split(pattern, string, maxsplit=0, flags=0)
pattern: 正则模型
string : 要匹配的字符串
maxsplit:指定分割次数
flags : 匹配模式
# 导入re模块
import re
# 根据正则匹配分割字符串,返回分割后的一个列表
# 语法:split(pattern,string,maxsplit,flags)
# maxsplit:指定分割次数
# 分割一次 ['z', 'zxlzz']
result = re.split("xlz","zxlzzxlzz",1)
# 分割两次 ['z', 'z', 'z']
# result = re.split("xlz","zxlzzxlzz",2)
# 没有匹配到字符串,以列表返回所有字符串 ['zxlxzzxlxzz']
# result = re.split("xlz","zxlxzzxlxzz",2)
print(result)
6.sub()函数
替换匹配成功的指定位置字符串,返回替换指定位置字符串后的字符串
sub(pattern, repl, string, count=0, flags=0)
pattern: 正则模型
repl : 要替换的字符串
string : 要匹配的字符串
count : 指定匹配个数
flags : 匹配模式
# sub()函数
# 导入re模块
import re
# 根据正则匹配替换匹配成功的指定字符
# 语法:sub(pattern,repl,string,count,flags)
# repl:要替换的字符串,count:指定匹配个数
# 替换一次 zpythonzxlzz
result = re.sub("xlz", "python", "zxlzzxlzz", 1)
# 替换两次 zpythonzpythonz
# result = re.sub("xlz", "python", "zxlzzxlzz", 2)
# 没有匹配到返回字符串 zxlxlxz
# result = re.sub("xlz", "python", "zxlxlxz", 1)
print(result)
7.subn()函数
替换匹配成功的指定位置字符串,以元组形式返回替换指定位置字符串后的字符串和替换次数,可以用两个变量分别接收
subn(pattern, repl, string, count=0, flags=0)
pattern: 正则模型
repl : 要替换的字符串
string : 要匹配的字符串
count : 指定匹配个数
flags : 匹配模式
# subn()函数
# 导入re模块
import re
# 根据正则匹配替换匹配成功的指定字符,
# 并且返回替换次数,可以用两个变量分别接收
# 语法:sub(pattern,repl,string,count,flags)
# repl:要替换的字符串,count:指定匹配个数
# 替换一次 zpythonzxlzz 1
result, num= re.subn("xlz", "python", "zxlzzxlzz", 1)
# 替换两次 zpythonzpythonz 2
# result, num = re.subn("xlz", "python", "zxlzzxlzz", 2)
# 没有匹配到返回字符串 zxlxlxz 0
# result, num = re.subn("xlz", "python", "zxlxlxz", 1)
print(result, num)
8.flags:匹配模式
标志 | 含义 |
---|---|
re.S(DOTALL) | 使匹配包括换行在内的所有字符 |
re.I(IGNORECASE) | 使匹配对大小写不敏感 |
re.L(LOCALE) | 做本地化识别(local-aware)匹配 |
re.M(MULTILINE) | 多行匹配,影响^和$ |
re.X(VERBOSE) | 该标志给予更灵活的格式以便将正则表达式写的更易理解 |
re.U | 根据Unicode字符集解析字符,这个标志影响\w\W\b\B |
9.正则表达式重点
1.r原生字符
将在python里有特殊意义的字符如\b,转换成原生字符(就是去除它在python的特殊意义),不然会给正则表达式有冲突,为了避免这种冲突可以在规则前加原始字符r;
2.正则表达式,返回类型为表达式对象的
如:<_sre.SRE_Match object; span=(6, 7), match=‘a’> 返回对象的,需要用正则方法取字符串,方法有:
group():获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来,groups():获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果groupdict():获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果;
3.匹配到的字符串里出现空字符
注意:正则匹配到空字符的情况,如果规则里只有一个组,而组后面是*就表示组里的内容可以是0个或者多过,这样组里就有了两个意思,一个意思是匹配组里的内容,二个意思是匹配组里0内容(即是空白)所以尽量避免用*否则会有可能匹配出空字符串;
import re
origin = "hello alex"
result = re.findall("(a)*",origin)
# 结果:['', '', '', '', '', '', 'a', '', '', '', '']
print(result)
4.()分组
注意:分组的意义,就是在匹配成功的字符串中,在提取()里,组里面的字符串;