六、python正则表达式

本文详细介绍了Python正则表达式的特性,如独立性和优势,包括高效查找和输入验证。涵盖了search(), match(), findall(), finditer(), fullmatch(), split()等核心函数,并讲解了转义、区间符号、重复模式、分组和标记等内容。通过实例演示,帮助读者掌握正则表达式在实际项目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.正则表达式的特点和优势

1.1 独立性

正则表达式运行的引擎是独立的,在几乎所有语言中都存在有正则表达式模块,正则表达式语法在各种语言上都是一样的,但是在实现方式上不尽相同。

1.2 优势

1.2.1 过滤查找
1.2.2 验证输入是否合法

2.正则搜索方法

2.1 search() & match()

2.1.1 search()match() 查找
	# 差异:
	re.search()依据正则表达式进行匹配
	re.match()只从字符串的开头匹配
	# 相同点:
	两者只会输出匹配找到的第一个符合要求的子字符串的match对象
	查找到结果返回match对象,没有则返回None
	# 实例
	import re  # 导入re模块
	ret1 = re.search(r"sanle", "hello sanle")  # 使用re.search()方法查找
	print(ret1)  # 返回一个match对象 或者 None  结果:<re.Match object; span=(6, 11), match='sanle'>
	print(ret1.group())  # 通过match对象的group属性,访问其内容 结果:sanle
	
	ret2 = re.match(r"hello", "hello sanle")  # 使用re.search()方法查找
	print(ret2)  # 返回一个match对象 或者 None  结果:None
	
	# result.start() result.end() 下标左闭右开区间 即[m,n)
	print(ret2.start())  # 输出匹配字符串的开始下标
	print(ret2.end())  # 输出匹配字符串的结束下标
	print(ret2.group())  # 输出匹配到的字符串
	
	# 结果:0 5 hello 即0->h ... 5->空格 hello为匹配到的字符串

2.2 findall() & finditer()

2.2.1 findall()和finditer()
	# 规则:
	# 相同点:
	findall 或 finditer 匹配所有符合要求的字符串
	# 不同点:
	findall找到所有匹配内容,放到一个列表里返回
	finditer找到所有内容,返回一个迭代器,惰性求值
	
	finditer 遍历后得到的每个内容都是一个match对象,需要调用group来得到里面的具体的匹配字符串
	findall 直接返回匹配的字符串列表
	# Pattern.findall(string[,pos][,endpos]) 查询所有匹配,结果受到分组影响
	# 如果没有分组,则返回与整个模式匹配的字符串列表。
	# 如果恰好有一个组,请返回匹配该组的字符串列表。
	# 如果存在多个组,则返回与组匹配的字符串的元组列表。
	# 非捕获组不会影响结果的形式。使用了分组之后,findall不会输出分组以外的内容。

	# 实例
	import re
	ret = re.findall("s.{6}","hello snale snachaung nihao world ssssssss")
	print(ret)  # findall 返回匹配字符串组成的列表
	
	# 结果:
	# ['snale s', 'sssssss']
	
	result = re.findall("s.{6}","hello snale snachaung nihao world ssssssss")
	for i in result:
	    print(i)  # findall 返回列表 遍历元素
	
	# 结果:
	# sanle s
	# sssssss
	
	
	ret = re.finditer("s.{6}","hello snale snachaung nihao world ssssssss") # 返回一个迭代器
	print(ret)  # finditer 返回iterator,即迭代器
	for i in ret:
	    print(i)  # 从迭代器中得到了match对象 需要调用其group来遍历其匹配字符串内容
	    print(i.group())  # 从match对象中得到匹配的字符串
	
	# 结果:
	# <callable_iterator object at 0x000001869ECDEF10>
	# <re.Match object; span=(6, 13), match='sanle s'>
	# sanle s
	# <re.Match object; span=(34, 41), match='sssssss'>
	# sssssss

	print(re.findall('[a-zA-Z]\d{2,}','a1bc22342459f9849'))  # ['c22342459', 'f9849']
	print(re.findall('[a-zA-Z](\d{2,})','a1bc22342459f9849'))  # ['22342459', '9849']
	# 使用分组功能,又要输出全部内容,那么就在整体外面再加一个括号
	print(re.findall('([a-zA-Z](\d{2,}))','a1bc22342459f9849'))  # [('c22342459', '22342459'), ('f9849', '9849')]


2.3 fullmatch() & split()

	# fullmatch(string[,pos[,endpos]]) 全部匹配
	import re
	print(re.search("张三","法外狂徒张三,来长沙了"))  # 整个字符串进行匹配 <re.Match object; span=(4, 6), match='张三'>
	
	print(re.match("张三","法外狂徒张三,来长沙了"))  # 只匹配字符串开始 None
	print(re.search("^张三","法外狂徒张三,来长沙了"))  # 只匹配字符串开始 None
	print(re.match("张三","法外狂徒张三,来长沙了"[4:]))  # <re.Match object; span=(0, 2), match='张三'>
	
	print(re.fullmatch("张三","法外狂徒张三,来长沙了"))  # 匹配字符串开始和结束位置 None
	print(re.search("^张三$","法外狂徒张三,来长沙了"))  # 匹配字符串开始和结束位置 None
	
	print(re.fullmatch("张三","法外狂徒张三,来长沙了"[4:6]))  # <re.Match object; span=(0, 2), match='张三'>
	
	# split(string,maxsplit=0) 根据匹配分割 受到分组的影响
	print(re.split('[+\-*/]','9+7-8*6/5'))  # 结果:['9', '7', '8', '6', '5']
	
	# 捕获分组 将匹配到的所有信息都匹配出来
	print(re.split('([+\-*/])','9+7-8*6/5'))  # 结果:['9', '+', '7', '-', '8', '*', '6', '/', '5']
	
	# maxsplit=0 指定分割的次数 默认是0不受限制
	print(re.split('(?:[+\-*/])','9+7-8*6/5',maxsplit=2))  # ['9', '7', '8*6/5']
	print(re.split('([+\-*/])','9+7-8*6/5',maxsplit=2))  # ['9', '+', '7', '-', '8*6/5']

2.4 正则表达式的转义

2.4.1 python中正则表达式转义工作流程
	python正则表达式转义两次,分别是python自己转义一次和正则自己转义一次如:\\\t -->\tab-->tab
	即 python自己转义\\为\  \t为tab键,之后交给正则来再一次转义即\tab转义为tab 自动忽略单个的\
	
	正则表达式前+r表示抑制第一次的python转义,使python
	直接将正则表达式传递给正则去转义,即只进行正则的转义,减少失误
	
	r'\tdv' -不转义字符,保持原始字符串 等价于 '\\tdv' 即表示以raw string格式进行定义,可以防止字符串规避反斜杠\的转义 直接将正则表达式传递给正则去转义
	f'gajeo{name}' -定义格式字符串
	b'12' -字符串bytes类型,以便服务器或浏览器识别bytes数据类型;
	
	print(u'中国')
	print(u'china')
	-字符串前面加u表示以Unicode格式进行编码,往往用来解决中文乱码问题,一般英文字符串基本都可以正常解析,而中文字符串必须表明用什么编码,否则就会乱码。
	# 实例
	import re
	result = re.search("snachaung \\ttongle", "hello world,snachaung \ttongle")
	print(result)
	
	# 结果: <re.Match object; span=(12, 29), match='snachaung \ttongle'>
	
	result = re.search(r"snachaung \\ttongle", "hello world,snachaung \ttongle")
	print(result)

	# 结果:None
	
	# 分析:前者没有+r即正则表达式进行了两次转义,先是\\t->\t,然后是\t->tab;后者是只经历 \\t->\tab 然后丢弃单个的\

3.正则表达式规则

3.1 正则替换和编译

3.1.1 正则替换
	# 格式:
	re.sub("匹配原则","替换内容",string)
	匹配的所有元素都替换
	# 实例
	import re
	str1 = "hello ,i'm learning python python"
	print(re.sub("p.{2}","xixi",str1))
	# hello ,i'm learning xixihon xixihon
3.1.2 正则编译
	import re
	msg = "hello my name is Jack Cali"
	msg2 = "hello my name is Rose"
	# 直接查找
	result = re.findall("is\s(.*)$", msg)
	result2 = re.findall("is\s(.*)$", msg2)
	print(result, result2)
	
	# 先编译再查找
	reg = re.compile("is\s(.*)$")
	print(reg.findall(msg))
	print(reg.findall(msg2))

	# 区别
	pass

3.2 正则表达式

区间

3.2.1 区间
	# 区间: [] 根据ascii码确定区间范围 --要求ascii码小的在前,ascii码大的在后面如:[a-z]a->97,z->122
	# 可以[A-z] A->65 z->122
	# [] 区间表示 任选括号里一个字符进行匹配
	# 实例
	import re
	ret = re.findall("[12pP]x", "2px 1xx Python pxoo")  # 匹配中括号内任意一个字符开头,且以x结尾的两个长度的字符串
	print(ret)
	ret = re.findall("[0-9]", "124354raskgreg-grme23")  # 匹配数字0-9任意字符
	print(ret)
	ret = re.findall("[A-Z]", "124354raskgreg-grme23")  # 匹配大写字母A-Z
	print(ret)
	ret = re.findall("[a-z]", "124354raskgreg-grme23")  # 匹配小写字母a-z
	print(ret)
	ret = re.findall("[A-Za-z0-9]", "124354raskgreg-grme23")  # 匹配大小写字母和数字0-9
	print(ret)
	ret = re.findall("[a-z0-9A-Z-]", "124354raskgreg-grme23")  # 匹配大小写字母和数字0-9及-
	print(ret)
3.2.2 区间取反
	ret = re.findall(r"[^A-z][0-9]","few2345rg43h6n5jdth")  # 匹配不以A-z开头且匹配第二位是0-9数字的字符串
	print(ret)

符号

3.2.3 匹配或
	import re
	msg = "四是四,十是十 十四是十四 四十是四十"
	ret = re.search(r"四|十", msg)
	print(ret.group())
	ret2 = re.findall(r"四|十", msg)
	print(ret2)
3.2.4 .占位符 
	# 表除(\n以外)的任意字符
	import re
	ret = re.findall("p.thon","pXthon python p-thon pthon p\nthon p thon")
	print(ret)
3.2.5 ^ $
	import re
	ret = re.findall(r"^python","python1 is python")
	print(ret)
	
	ret = re.findall(r"python$","python1 is python")
	print(ret)
	
	ret = re.findall(r"^python$","python1 is python")
	print(ret)
3.2.6 正则重复
	# 通配符: * ? +
	# ? 匹配前一项0次或1次
	# + 匹配前一项1次以上 1-n次
	# * 匹配前一项任意次 0-n次
	# {n,m} 匹配前一项n-m次 {n,} {,m} {n}
	# 实例
	import re
	ret = re.findall('py?', "pythonppyy")
	print(ret)  # 结果:['py', 'p', 'py']
	
	ret = re.findall('py+', "pythonppyy")
	print(ret)  # 结果:['py', 'pyy']
	
	ret = re.findall('py*', "pythonppyy")
	print(ret)  # 结果:['py', 'p', 'pyy']
	
	ret = re.findall('py{1,3}', "pythonppyy")
	print(ret)  # 结果:['py', 'pyy']
	
	ret = re.findall('py{1,}', "pythonppyyyy")  # 匹配前一项1次到多次
	print(ret)  # 结果:['py', 'pyyyy']
	
	ret = re.findall('py+', "pythonppyyyy")  # 匹配前一项1次到多次
	print(ret)  # 结果:['py', 'pyyyy']
	
	ret = re.findall('py{,3}', "pythonppyyyy")  # 匹配前一项3次以下
	print(ret)  # 结果:['py', 'p', 'pyyy']
	
	ret = re.findall('py{3}', "pythonppyyyy")  # 匹配前一项3次
	print(ret)  # 结果:['pyyy']

快捷标识

3.2.7 快捷标识
	\A 匹配字符串开始
	\b 匹配词边界
	\B 匹配非词边界
	\w 匹配单词字符 a A 123 中文
	\W 匹配非单词字符
	\d 匹配数字
	\D 匹配非数字
	\s 匹配空白
	\S 匹配非空白
	# 实例
	# 匹配字符串的开始
	import re
	ret = re.findall(r"\Ahello", "hello world hello")
	print(ret)
	
	# 词边界
	ret = re.findall(r"\bword\B", "word123 word# abcword #word你好")
	print(ret)
	
	# 匹配单词字符
	ret1 = re.findall(r"\wword\W", "word123 word# abcword #word你好")
	print(ret1)
	
	ret2 = re.findall(r"\wword\W", "中国word*56w A1word# abcword #word你好")
	print(ret2)
	
	# 匹配数字和非数字
	ret = re.findall(r"\dword\D", "word123 1word# abcword #word你好")
	print(ret)
	
	# 匹配空白和非空白
	ret = re.findall(r"\sword\S", "word123 word# abcword #word你好")
	print(ret)

^ $

	import re
	ret = re.findall(r"^python","python1 is python")  # 匹配字符串以python开头的python字符串
	print(ret)  # 结果:['python']
	
	ret = re.findall(r"python$","python1 is python")  # 匹配字符串以python结尾的python字符串
	print(ret)  # 结果:['python']
	
	ret = re.findall(r"^python$","python1 is python")  # 匹配以python字符串开头和结尾的python字符串
	print(ret)  # 结果:[]

正则重复

	# 通配符: * ? +
	# ? 匹配前一项0次或1次
	# + 匹配前一项1次以上 1-n次
	# * 匹配前一项任意次 0-n次
	# {n,m} 匹配前一项n-m次 {n,} {,m} {n}
	import re
	ret = re.findall('py?', "pythonppyy")
	print(ret)  # 结果:['py', 'p', 'py']
	
	ret = re.findall('py+', "pythonppyy")
	print(ret)  # 结果:['py', 'pyy']
	
	ret = re.findall('py*', "pythonppyy")
	print(ret)  # 结果:['py', 'p', 'pyy']
	
	ret = re.findall('py{1,3}', "pythonppyy")
	print(ret)  # 结果:['py', 'pyy']
	
	ret = re.findall('py{1,}', "pythonppyyyy")  # 匹配前一项1次到多次
	print(ret)  # 结果:['py', 'pyyyy']
	
	ret = re.findall('py+', "pythonppyyyy")  # 匹配前一项1次到多次
	print(ret)  # 结果:['py', 'pyyyy']
	
	ret = re.findall('py{,3}', "pythonppyyyy")  # 匹配前一项3次以下
	print(ret)  # 结果:['py', 'p', 'pyyy']
	
	ret = re.findall('py{3}', "pythonppyyyy")  # 匹配前一项3次
	print(ret)  # 结果:['pyyy']

贪婪模式和非贪婪模式

	# 贪婪模式 尽可能地匹配长的字符串
	# 非贪婪模式 从左至右依次匹配 匹配到就结束本字段匹配 然后进行后面的字符串匹配 (+? *? {2,4}?)
	
	# 默认为贪婪模式
	import re
	ret = re.findall("py*","pythonpyyyyy")
	print(ret)  # 结果:['py', 'pyyyyy']
	
	# 非贪婪模式
	import re
	msg = "cats and dogs,cats1 and dogs1"
	print(re.findall(r"c.*?s",msg))  # 结果:['cats', 'cats']
	
	import re
	ret = re.findall("py*?","pythonpyyyyy")
	print(ret)  # 结果:['p', 'p']

正则分组

	# group 默认参数是0 表示输出整个匹配字符串
	#        参数 n (n>0)输出第几个组的匹配字符串
	msg = "tel:173-7572-2991"
	ret = re.search(r"(\d{3})-(\d{4})-(\d{4})",msg)
	print(ret.group())  # 输出匹配到的字符串
	print(ret.group(0))  # 输出匹配到的字符串
	print(ret.group(1))  # 输出匹配到的第一组的子字符串
	print(ret.group(2))  # 输出匹配到的第二组的子字符串
	print(ret.group(3))  # 输出匹配到的第三组的子字符串

分组向后引用

	# 前面的匹配内容会保存在内存里面,后面匹配从内存里查找
	msg = "tel:173-7572-2991"
	msg = "tel:173-7572-173"
	ret = re.search(r"(\d{3})-(\d{4})-\1", msg) # \1表示匹配第一组子字符串
	print(ret.group())  # 只有match对象才有group属性  AttributeError: 'NoneType' object has no attribute 'group'
	# 结果:173-7572-173

捕获分组和非捕获分组

	# 捕获分组
	# 分组之后匹配到的数据会发放在内存里,并且给定一个从1开始的索引
	# 捕获分组是可以进行分组向后引用
	
	# 非捕获分组(?:正则表达式)
	# 只分组不捕获 匹配到的分组数据不放在内存里
	# 不能使用分组向后引用
	import re
	msg = "tel:173-7572-7572"
	ret = re.search(r'(?:\d{3})-(\d{4})-\1', msg)
	print(ret.group(0))  # 打印匹配字符串 结果:173-7572-7572
	print(ret.group(1))  # 打印第一个捕获分组  结果:7572
	
	# 如果有捕获分组 findall只会匹配捕获分组里的内容
	import re
	msg = "tel:173-7572-7572"
	ret = re.findall(r'(?:\d{3})-(\d{4})-\1', msg)
	print(ret)  #结果:['7572']

命名分组

	# 命名分组 (?P<名字>正则表达式)
	import re
	msg = "tel:173-7572-7572"
	ret = re.search(r'(?P<first>\d{3})-(\d{4})-\2', msg)
	print(ret.group())
	print(ret.group("first"))
	print(ret.groupdict())
	
	# 结果:173-7572-7572
	173
	{'first': '173'}

正则标记

	# 正则标记 --改变正则表达式的默认匹配规则 如大小写是否敏感
	msg = """YOU JUMP, I GO
	you jump, i go"""
	# 对大小写不敏感的标记
	ret = re.findall(r"JUMP", msg, re.I)  # 忽略大小写
	print(ret) # 结果:['JUMP', 'jump']
	
	# 多行模式
	ret = re.findall(r"^YOU JUMP, I GO$", msg, re.I | re.M)  # 忽略大小写 且运用多行模式
	print(ret)  # 结果:['YOU JUMP, I GO', 'you jump, i go'] 
	
	# re.S 让.匹配任意字符 包括换行符
	ret = re.findall(r"^you.*go$", msg, re.I | re.S)  # 忽略大小写 且让.匹配任意字符包括换行符
	print(ret)  # 结果:['YOU JUMP, I GO \nyou jump, i go']

零宽断言

	# 零宽断言
	# 不占用匹配宽度,只用来确定位置
	# 与驴不占用匹配宽度,只用来确定位置
	str1 = "红鲤鱼与绿鲤鱼与驴"
	print(re.findall(r".鲤鱼(?=与驴)", str1))  # 匹配后面有与驴的鲤鱼
	print(re.findall(r".鲤鱼(?!与驴)", str1))  # 匹配后面没有与驴的鲤鱼
	print(re.findall(r"(?<=红)鲤鱼.", str1))  # 匹配前面有红的鲤鱼
	print(re.findall(r"(?<!红)鲤鱼.", str1))  # 匹配前面没有红的鲤鱼

内联标记

	# 修饰符         功能
	# (?imx)re   正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
	# (?imx:re)   在括号中使用i, m, 或 x 可选标志
	# 内联标记 只想在某个地方使用忽略 而不在其他地方忽略?可以使用内联标记
	# 内联标记实际就是匹配模式的部分范围生效
	# re.IGNORECASE 与 (?i:) 括号内忽略大小写
	# re.MULTILINE 与 (?m:) '^'和'$'的跨行限制开头结尾 括号内实现多行模式
	# re.DOTALL 与 (?s:) 让 '.'支持换行符的匹配。 括号内实现.代表所有字符包括换行/n
	# re.VERBOSE 与 (?x:) 支持注释 括号内实现注释
	# re.ASCII 与 (?a:) 让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII 括号内只匹配ascii
	
	# (?i:正则表达式) 括号内大小写不敏感
	a = re.compile("(super) APP")
	x = a.search("SUPER APP")
	print(x)                #不能用super匹配SUPER
	
	a = re.compile("(?i:super) APP")  # 忽略大小写进行匹配
	x = a.search("SUPER APP")
	print(x)       #<re.Match object; span=(0, 9), match='SUPER APP'>     #可以用super匹配SUPER 。
	
	
	# (?i)re
	import re
	ret = re.findall('(?i)^python$','PYTHON')  # 忽略大小写
	print(ret)  # 结果:['Python']
	ret = re.findall('(?i)^python$','Python\npython')
	print(ret)  # 结果:[]
	ret = re.findall('(?im)^python$','Python\npython')  #多行模式
	print(ret)  # 结果:['Python', 'python']
	
	# (?imx:re)
	import re
	msg = "Hello Python"
	ret = re.findall('(?i:hello) python',msg)
	print(ret)  # 结果:[]
	ret = re.findall('(?i:hello) Python',msg)
	print(ret)  # 结果:['Hello Python']
	
	# (?is:re) 大小写不敏感 且.代表左右的字符串包含换行\n
	a = re.compile(r'(?i:天天.*up)')
	str_ = '天天UP天天\nUP'
	x = re.match(a,str_)
	print(x)       #<re.Match object; span=(0, 4), match='天天UP'>     #点号不能匹配换行符
	
	a = re.compile(r'(?is:天天.*up)')
	str_ = '天天UP天天\nUP'
	x = re.match(a,str_)
	print(x)     #<re.Match object; span=(0, 9), match='天天UP天天\nUP'>    #支持忽略大小写,并让点号匹配换行符
	
	# 排除标记方式
	
	# 比如flasg属性中 已经制定了忽略大小写 但是在某些地方一定会
	# 不能忽略大小写 那么就可以设置排除标记方式
	# 格式:(?-im:re) im为要忽略的属性 可以是其他任何存在的属性
	
	a = re.compile(r'(?-i:None).*empty',re.IGNORECASE)
	str_1 = 'none expressing EMPTY'
	str_2 = 'None expressing EMPTY'
	x = a.match(str_1)
	print(x)  # 结果:None 因为str_1中none大小写敏感 所以无匹配项
	
	y = a.match(str_2) # 分组内大小写敏感 分组外大小写不敏感
	print(y)  # 结果:<re.Match object; span=(0, 21), match='None expressing EMPTY'>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值