Python_14:正则表达式

一、基本概念

1.1 什么是正则表达式

​ 正则表达式(Regular Expression)也叫做匹配模式。它是由一组具有特定含义的字符串组成,通常用于匹配和替换文本。正则表达式是一门独立的技术,被很多编程语言实现了。

1.2 为什么使用正则表达式

​ 在软件开发过程中,经常会涉及到大量的关键字等各种字符串的操作,使用正则表达式能很大程度的简化开发的复杂度和开发的效率,所以在 Python中正则表达式在字符串的查询匹配操作中占据很重要的地位。

1.3 Python中的re模块

>>> import re
>>> dir(re)
['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'Match', 'Pattern', 'RegexFlag', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_cache', '_compile', '_compile_repl', '_expand', '_locale', '_pickle', '_special_chars_map', '_subx', 'compile', 'copyreg', 'enum', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'functools', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'template']

常用方法:

  • findall() 查找所有,返回一个列表
  • finditer() 查找所有,返回一个迭代器
  • match() 从匹配,匹配以xxx开头
  • search() 只会查找一次
  • split() 分割
  • sub() 替换

举个例子:

>>> s = "今天天气真好"
>>> res = re.match("今天", s)
>>> res
<re.Match object; span=(0, 2), match='今天'>
>>> res.group()
'今天'
>>> res1 = re.match("天气", s)		#以"天气"开头,匹配为none
>>> res1
>>>

>>> s
'啊10环,你比9环多1环'
>>> re.sub("10", "1", s)
'啊1环,你比9环多1环'

>>> re.split("\.", "www.baidu.com")
['www', 'baidu', 'com']

二、元字符

单个字符的匹配

代码说明
.任意符号(除换行符 \n)
\d匹配数字
\w匹配有效符号(大小写字母、数字、下划线、各国语言符号)
\s匹配空白位(空格、\t)
^以xx开头
$以xx结尾,8$ 以8结尾
[]列举。其中 - 是在acsii表中的范围
#	\d		匹配数字,其他均不匹配
>>> re.match("\d", "5")
<re.Match object; span=(0, 1), match='5'>
>>> re.match("\d", "a")
>>> re.match("\d", "A")
>>> re.match("\d", "+")
>>>

#	.		匹配任意字符,除换行符
>>> re.match(".", "1")
<re.Match object; span=(0, 1), match='1'>
>>> re.match(".", "a")
<re.Match object; span=(0, 1), match='a'>
>>> re.match(".", "A")
<re.Match object; span=(0, 1), match='A'>
>>> re.match(".", "+")
<re.Match object; span=(0, 1), match='+'>
>>> re.match(".", "\n")
>>>						#"\n"没有匹配

#	\w		匹配有效字符
>>> re.match("\w", "a")
<re.Match object; span=(0, 1), match='a'>
>>> re.match("\w", "A")
<re.Match object; span=(0, 1), match='A'>
>>> re.match("\w", "_")
<re.Match object; span=(0, 1), match='_'>
>>> re.match("\w", "9")
<re.Match object; span=(0, 1), match='9'>
>>> re.match("\w", "+")
>>>						#没有匹配,返回None

#	\s		匹配空白符
>>> re.match("\s", " 123")
<re.Match object; span=(0, 1), match=' '>
>>> re.match("\s", "\t 123")
<re.Match object; span=(0, 1), match='\t'>
>>> re.match("\s", "abc\t 123")
>>>


#	^		以xx开头	match本来就有从头匹配的功能,所以用findall配合使用
>>> re.findall("^1.*", "1abc")	#以1开头,后面任意
['1abc']
>>> re.findall("^1.*", "abc")
[]

#	$		以xx结尾
>>> re.match("^1\d*8$", "18")				#以1开头,以8结尾。中间全部是数字
<re.Match object; span=(0, 2), match='18'>
>>> re.match("^1\d*8$", "12348")
<re.Match object; span=(0, 5), match='12348'>
>>> re.match("^1\d*8$", "1abc8")
>>>#没有匹配,返回None

#	[]	列举
>>> re.match("[0123456789]", "1")			#[0123456789]等效于\d
<re.Match object; span=(0, 1), match='1'>
>>> re.match("[0123456789]", "a123")
>>>#没有匹配,返回None
>>> re.match("[0123abc]", "a123")			#[0123abc]其中任意一个开头即可
<re.Match object; span=(0, 1), match='a'>

>>> re.match("[a-z]", "a123")				#-符号是按照ascii表范围定义
<re.Match object; span=(0, 1), match='a'>
>>> re.match("[A-Z]", "ABCa123")
<re.Match object; span=(0, 1), match='A'>
>>> re.match("[0-9]", "123")
<re.Match object; span=(0, 1), match='1'>
>>> re.match("[A-Za-z]", "abc123")			#大小写符号		
<re.Match object; span=(0, 1), match='a'>
>>> re.match("[A-Za-z0-9_]", "ABCabc123")	#有效符号
<re.Match object; span=(0, 1), match='A'>
  • 匹配中文:
>>> re.match("[\u4e00-\u9fa5]", "中文")
<re.Match object; span=(0, 1), match='中'>
>>> re.match("[\u4e00-\u9fa5]", "abc中文")
>>>

三、反义符

也是元字符:单个字符的匹配

代码说明
\D非数字
\W特殊符号
\S非空白位
[^abc]不能是abc其中任意一个
#\D匹配非数字
>>> re.match("\D", "abc")
<re.Match object; span=(0, 1), match='a'>
>>> re.match("\D", "123")
>>>

#\W特殊符号
>>> re.match("\W", "???")
<re.Match object; span=(0, 1), match='?'>
>>> re.match("\W", "abc")
>>> re.match("\W", "123")
>>>

#\S非空白位
>>> re.match("\S", " ")
>>> re.match("\S", "\t")
>>> re.match("\S", "as")
<re.Match object; span=(0, 1), match='a'>

四、转译符

在Python中 \ 符号本身具有特殊意义。

>>> s = "hello \nworld"
>>> print(s)
hello
world

#如果字符串内容原本就包含 \nworld,添加\进行转义。
#第一个\是转译符,第二个\就是普通的\(不具有特殊意义)。
>>> ss = "hello \\nworld"
>>> print(ss)
hello \nworld

在python的字符串中\是具有特殊含义的,要正常表示一个\,需要两个\来表示。在正则中,\是具有特殊含义的,要正常表示一个\,需要两个\来表示

>>> path = "c:\\a\\b\\c"							#字符串中的 \ 
>>> print(path)
c:\a\b\c

>>> re.match("c:\\\\a\\\\b\\\\c", path)		#四个\。正则转一次,字符转转一次
<re.Match object; span=(0, 8), match='c:\\a\\b\\c'>
#第一个\转义第二个\,第三个\转义第四个\。然后两个\\字符串再转一次

推荐使用:re.match(r"")

r的作用:只关心正则的转义,并不关系字符串的转义

>>> re.match(r"c:\\a\\b\\c", path)
<re.Match object; span=(0, 8), match='c:\\a\\b\\c'>

建议以后在写正则的时候,一定要在正则表达式前面加上r

五、重复匹配(多位匹配)

代码说明
*匹配任意位(0~∞)
+至少一位(1~∞)
==0位==或者1位
{n}有n位
{n,}至少n位
{n,m}n~m位
>>> s = "啊10环,你比9环多1环"
>>> re.findall(r"\d", s)
['1', '0', '9', '1']

#	*
>>> re.match(".*", s)
<re.Match object; span=(0, 12), match='啊10环,你比9环多1环'>

#	+
>>> re.findall(r"\d+", s)
['10', '9', '1']	#对比['1', '0', '9', '1']

#	{}	指定位数
#以1开头,第二位是[34566789]其中一个,后面还有9位
>>> re.findall(r"1[356789]\d{9}", "1334567890123456789")
['13345678901']
#至少9位
>>> re.findall(r"1[356789]\d{9,}", "1334567890123456789")
['1334567890123456789']

r"</?.*?>" 匹配HTML标签 第一个?/?表示有/或者没有/ 第二个?是非贪婪模式

六、分组

在正则表达式中,使用圆括号 () 将表达式包裹起来,会形成正则匹配后的二次筛选。

>>> res = re.match(r".*?(\d+).*", s)
>>> res
<re.Match object; span=(0, 12), match='啊10环,你比9环多1环'>
>>> res.group()
'啊10环,你比9环多1环'
>>> res.group(1)		#原正则中,只有一个()
'10'					#对(\d+)进行二次匹配

>>> re.findall(r".*?(\d+).*", s)
['10']			#直接是二次筛选后的结果
>>> re.match(r"<\w+>.*</\w+>", "<a>连接地址</a>")
<re.Match object; span=(0, 11), match='<a>连接地址</a>'>
>>> re.match(r"<\w+>.*</\w+>", "<a>连接地址</b>")
<re.Match object; span=(0, 11), match='<a>连接地址</b>'>
#匹配<a></b>是有问题的

>>> re.match("<(\w+)>.*</\\1>", "<a>连接地址</a>")
<re.Match object; span=(0, 11), match='<a>连接地址</a>'>
>>> re.match(r"<(\w+)>.*</\1>", "<a>连接地址</a>")
<re.Match object; span=(0, 11), match='<a>连接地址</a>'>
>>> re.match(r"<(\w+)>.*</\1>", "<a>连接地址</b>")
>>>#没有匹配,返回None

re.match(r"<(\w+)>.*</\1>", “连接地址”) \1代表了第一个括号中的值

七、贪婪模式与非贪婪模式(懒惰模式)

Python,默认使用贪婪模式。尽可能匹配更多的字符

>>> ss
'\n<div>\n这是内容\n</div>\n<div>\n这是内容\n</div>'
>>> ss = re.sub(r"\n", "", ss)
>>> ss
'<div>这是内容</div><div>这是内容</div>'
>>> re.findall(r"<\w+>(.*)</\w+>", ss)
['这是内容</div><div>这是内容']					#贪婪模式

>>> re.findall(r"<\w+>(.*?)</\w+>", ss)
['这是内容', '这是内容']						#非贪婪模式

在 *、?、+、{n,m} 后面加上 ? ,可以将贪婪模式变为非贪婪模式。

代码说明
*?重复任意次,但是尽可能少重复
+?重复1次或者多次,但是尽可能少重复
??重复0次或者1次,但是尽可能少重复
{n,m}?重复n到m次,但是尽可能少重复
{n,}?重复n次以上,但是尽可能少重复
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值