正则的基本用法


day6 — 正则表达式


1.正则表达式
# (1).什么是正则
根据指定规则从字符串中提取子字符串
指定规则: 正则表达式
字符串: 待匹配字符串
子字符串: 匹配结果
注意: 正则并不是python独有的, 各种语言中均可以使用正则

# (2).正则表达式应用场景
1.表单验证(手机号验证, 账号验证, 密码验证)
2.爬虫
3.其他

2.正则表达式语法
# 1.元字符
(1) .(): 匹配任意字符, 换行符除外\n ****
(2) []: 字符组, 一些特殊的字符组如下: ****
    [a-z]: a到z的任意小写字母
    [A-Z]: A到Z的任意大写字母
    [0-9]: 09的任意数字
(3) \d: 匹配任意数字  *****
(4) \D: 匹配非数字
(5) \s: 匹配空白符
(6) \S: 匹配非空白符
(7) \w: 匹配数字字母下划线 ****
(8) \W: 匹配非数字字母下划线
(9) ^: 以什么开头  *****
(10) $: 以什么结尾  *****
    
# 小练习:
1.用户输入一个字符串, 这个字符串中可能包含abc?def类型的子字符串, 先需要匹配出字符串中的abc, def及其之间的那个字符, 如skfjabc9deflskjdf
- 正则表达式: abc.def
- 解释: 因为确定abc与def之间只有一个字符, 所以abc和def直接写死就好了, 那他们之间的那个字符是什么不确定, 所以用.来代表可以是任意一个字符.
- 思考: 如果不确定abc与def之间到底有几个字符怎么办, 有可能是1, 有可能是多个, 还有可能没有.....

2.接收用户输入, 使用正则匹配出字符串中的所有数字, 如abd23kjsd9 --> 2, 3, 9
- 正则表达式: [0-9]  or \d
- 解释: []代表字符组, 0-9代表09之间的任意数字, 也可以用\d代表任意数字
- 思考: 如果我不想让23匹配出来是分开的怎么办呢, 比如我要计算字符串中数的和, 上面的例子要求计算的是23+9, 但是如果使用上面的正则表达式匹配出来的是2, 3, 9, 则计算的是2+3+9.
# 2.量词: 匹配字符的数量
*: 匹配0个或无数个
+: 匹配1次过无数个
?: 匹配1个或0{m}: 匹配m个
{m,n}: 匹配n个到m个
{m,}: 匹配至少m个
{,n}: 匹配至多n个
    
# 遗留问题解决:
1.用户输入一个字符串, 这个字符串中可能包含abc???...def类型的子字符串, 先需要匹配出字符串中的abc, def及其之间的哪个字符
正则表达式: abc.*def
解释: abc和def是确定的, 中间用.代表匹配任意字符, *代表可以没有字符, 也可以有多个字符
问题: 如果用上面的正则表达式匹配: ksabc89def-78abc666def, 结果还尽如人意吗?

2.接收用户输入, 使用正则匹配出字符串中的所有数字, 如abd23kjsd9
正则表达式:  \d+
解释: \d代表任意数字, +代表匹配1个或多个
# 3.贪婪匹配与非贪婪匹配
(1).贪婪匹配是指在正则匹配的过程中尽量往多了匹配, 正则表达式默认是贪婪匹配.
如上面的例子: ksabc89def-78abc666def字符串使用abc.*def进行匹配, 根据正则表达式第一次会从ks后边的abc考试向后匹配, 遇到89后面的def起始已经满足条件了, 但正则是贪婪的, 他先匹配跟多的字符出来, 于是继续向后找, 直到找到最后的def, 他发现从ks后面的abc开始, 一直到最后的def之间有很多字符, 并且之间的字符满足.*的匹配规则, 所以他就都给匹配出来了
(2).非贪婪匹配是指一但满足正则表达式,就将匹配到的作为一个结果, 然后继续向后匹配, 在匹配到一段满足正则表达式的子字符串又作为一个结果, 直到找不出满足正则表达式的结果为止. 换言之, 就是一个子字符串尽量往少了匹配.
非贪婪匹配需要在量词后面使用?进行修饰
如上面的例子: ksabc89def-78abc666def使用abc.*?def进行匹配即可得到'abc89def''abc666def'两个结果
# 4.分组与或
# 分组:
(1).分组: 是在正则表达式中使用()将正则表达式的一部分括起来表示一部分
(2).作用: 
    改变优先级 *****
    分组引用
    分组捕获
    
# 或的使用: 用"|"分隔的正则表达式, 代表按照|两边的正则表达式进行匹配都行
(1).使用的符号: |  (管道符)
(2).示例:
    abc(\d+|def)
    解释: 正则表达式前面的abc是固定的, 必须匹配abc三个字母, abc后面是1个或多个数字可以作为匹配结果, abc后面是def三个字母也满足正则表达式, 比如按照上面的正则表达式对"abc789---abcdef999"的匹配结果为abc789和abcdef

**做一做: **

1.利用正则匹配出字符串中的所有数, 比如s = 'abc123kdfj789', 匹配结果为123, 789

2.利用正则匹配出以a开头, 以z结尾的字符串

3.匹配出字符串s = 'jjabckkksdjfabc89kkk'中abc???...kkk形式的字符串, abc与kkk之间可能有任意多个任意字符

4.匹配字符串中的所有合法手机号, 手机号共11位数字, 第一位以1开头, 第二位数为的数字在3-8之间, 其余为9个任意数字
s = 'kdjfs你好13724265588克里斯京东方17679962330kjsldf11324567982'

5.提取出下面HTML代码中的所有图片的src连接
html = '''
<html>
	<head>
		<title>
			美女
		<title>
	</head>
	<body>
	<img src="//img.ivsky.com/img/bizhi/li/201911/20/yinger-004.jpg" alt="美女明星颖儿桌面壁纸">
	<img src="//img.ivsky.com/img/bizhi/li/201911/18/fujing-002.jpg" alt="美女歌手傅菁桌面壁纸">
	<img src="//img.ivsky.com/img/bizhi/li/201910/30/yangmi-006.jpg" alt="美女明星杨幂桌面壁纸">
	<img src="//img.ivsky.com/img/bizhi/li/201910/30/nini.jpg" alt="美女明星倪妮桌面壁纸">
	</body>
</html>
'''

3.re模块
# re模块是做什么的
re模块是python提供正则的接口模块, 让你能够在python程序中使用正则

# 重点掌握以下方法:
1.re.findall()
2.re.match()
3.re.search()
4.re.compile()
3.1 findall方法
# re.findall(r'expression', str): 扫描整个字符串, 以列表形式返回所有匹配到的结果
import re
s = 'k789lfsdkjf123sldkjfoe666'
ret = re.findall(r'\d+', s)
print(ret)

# 拓:分组的妙使用
s = '<img src="https://enterdesk.com/kjsdlfj/soiejfn/2020/6/21/jlsjfdls.jpg"></img>'
ret = re.findall(r'src="(.*?)"', s)
print(ret)
3.2 match方法
# re.match(r'expression', str): 从字符串开头进行匹配, 如果开头就不符合则匹配不到结果返回None, 如果匹配到结果后返回一个对象, 使用group进行取值
import re
s1 = 'a789lfsdkjfa123sldkjfoa666'
ret1 = re.match(r'a\d+', s)
print(ret1)
print(ret1.group())

s2 = 'a789lfsdkjfa123sldkjfoa666'
ret2 = re.match(r'a\d+', s)
print(ret2)
print(ret2.group())

# 注意: 在使用match进行正则匹配时, 不可对匹配结果直接使用group()进行取值, 因为group()是匹配对象的方法, 但在程序中并不能确定一会能够匹配到结果返回一个对象, 当匹配不到结果的时候会返回None, 而None不是匹配结果对象. 所以None没有group()方法, 直接对匹配结果使用group()可能会报错.
3.3 search()方法
# re.search(r'expression', str): 从头开始扫描字符串, 匹配到一个结果就立即返回该结果对象, 使用group()进行取值, 如果匹配不到结果则返回None.
import re
s = 'a789lfsdkjfa123sldkjfoa666'
ret = re.search(r'\d+', s)
print(ret)
print(ret.group())
3.4 compile方法
# re.compile(r'expression'): 用于编译正则表达式, 便于后续使用
# 示例:
import re
pattern = re.compile(r'\d+')
ret = pattern.findall("jslkdfj789ksjdf")
print(ret)

# 你的疑问: 为啥要脱掉裤子排出废气?
1.compile可以编译正则表达式, 对于复杂的表达式编译一次即可在后续使用
2.经过编译的正则表达式, 在匹配是效率更高
# 实测差别不大(测试不太严谨, 哈哈哈)
# 利用装饰器测试使用compile和不适用compile进行正则匹配的效率
...

拓展:
# 回溯:
1.一个细致的匹配过程
对字符串"abcsdfsdfsdf1234"使用"abc\w+\d{3}"进行正则匹配

2.回溯概念:
往回退的操作就是回溯

# 优化:
1、使用正确的边界匹配器(^、$等),限定搜索字符串位置
2、使用具体的元字符、字符类(\d、\w、\s等) ,少用”.”字符
3、使用正确的量词(+*、?、{n,m}),如果能够限定长度,匹配最佳

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值