python语法基础---正则表达式(补充)

发布于:2024-12-06 ⋅ 阅读:(26) ⋅ 点赞:(0)

🌈个人主页:羽晨同学 

💫个人格言:“成为自己未来的主人~” 

上一篇文章中,我们讲到了贪婪匹配和非贪婪匹配,我们在这篇文章中,主要讲的就是贪婪匹配和非贪婪匹配的剩下的部分,话不多说,让我们开始吧。

我们先来看几个例子,大家可以相一下这个打印出来的结果是什么。

import re
print(re.findall(r"a\w+",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"\w+b",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"a\w+b",'afasfadasafa464646_fafdasda_dasdasdfb'))

这个就是打印出来的结果。

这个前面第一个正则表达式的意思是说,从a开始,中间进行贪婪匹配,直到结束。

第二个正则表达式的意思直接进行贪婪匹配,然后到b结束。

第三个正则表达式的意思是说,从a开始,中间进行贪婪匹配,然后到b结束。

你看,虽然这三个打印出来的结果是相同的,但是,其中表达的意思并不相同。

我们再来看下一个例子:

print(re.findall(r"a\w+?",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"\w+?b",'afbsfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"a\w+?b",'afbsfadasafa464646_fafdasda_dasdasdfb'))

这个是我们这次打印出来的结果,你看是不是有很大的不同。

对于贪婪匹配后面加一个?,这样子就变成了非贪婪匹配。

所以,对于第一个正则表达式而言,要找到的,是所有以a开头的字符串,并且由于是非贪婪匹配,并不无限向后找,碰到下一个a的时候,就构成了一个新的字符串。

对于第二个正则表达式而言,找到的是所有以b结尾的字符串。

对于第三个正则表达式而言,找到的是所有的以a开头,以b结尾的字符串作为元素。

我们再来看下一组表达式

print(re.findall(r"a\w*?",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"\w*?b",'afbsfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"a\w*?b",'afbsfadasafa464646_fafdasda_dasdasdfb'))

print(re.findall(r"a\w*",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"\w*b",'afasfadasafa464646_fafdasda_dasdasdfb'))
print(re.findall(r"a\w*b",'afasfadasafa464646_fafdasda_dasdasdfb'))

这个当中,其实需要强调的是,*表示的是0个或者多个,因为后面加上了?,所以只能找到a

我们再来看下一组代码。

import re
print(re.findall(r"\d+","fhig346-gh465464nm"))
print(re.findall(r"[a-z]+","fhig346-gh465464nm"))
# 正则1 |正则2
print(re.findall(r"\d+|[a-z]+","fhig346-gh465464nm"))

通过这个代码,我们可以了解到的是,这个|,其实就是或的意思。

我们来看下一组代码

import re
print(re.findall(r"(\d+)|[a-z]+","fhig346-gh465464nm"))
# ['', '346', '', '465464', '']
print(re.findall(r"\d+|([a-z]+)","fhig346-gh465464nm"))
print(re.findall(r"(\d+)|([a-z]+)","fhig346-gh465464nm"))

默认情况下,如果正则表达式中出现(),结合findall查找,最终的结果中只显示()的结果。这个也叫做捕获组

有捕获组,那肯定也存在着非捕获组,我们来看一下非捕获组的示例。

# b、非捕获组:(?:正则)
print(re.findall(r"(?:\d+)|[a-z]+","fhig346-gh465464nm"))
# ['fhig', '346', 'gh', '465464', 'nm']
print(re.findall(r"\d+|(?:[a-z]+)","fhig346-gh465464nm"))
# ['fhig', '346', 'gh', '465464', 'nm']

你看,这个就是非捕获组,在这种情况下面,()是不会起作用的。

练习,已知一个字符串data,检索其中合法的邮箱

data = 'yz@163.comhellodasdasda@sina.com146747@qq.com4654654@xxx.com'
import re
mall_list=re.findall(r"\w+@(?:163|126|qq|sina)\.com",data)
print(mall_list)

这样子,我们就拿到了我们想要的结果。

我们接下来讲一下正则表达式中的几个常用的函数。

1. compile():将正则字符串编译成正则对象,一般都是为了结合其他函数使用的

2. match():用正则匹配指定字符串中的内容,如果匹配上,返回Match对象
如果未匹配上,则返回None
应用:判断用户名或密码是否合法

3. search():用正则搜索指定字符串中的内容,如果匹配上,返回Match对象,如果未匹配,返回None
注意,只会查找一次

4. findall():用正则搜索指定字符串中的内容,如果匹配上,返回非空列表,如果未匹配,返回空列表
注意:查找所有
应用:全局搜索数据,在爬虫中一般使用findall

5.finditer():用正则搜索指定字符串中的内容,返回一个迭代器,
如果匹配上,则返回一个Match对象
注意,查找所有

下面,我们来写一下对应的应用这些函数的代码。

首先,我们来看第一个例子:

import re
r=re.findall(r"a\d","6a8ghjkasda3asdaa8")
print(r)
r=re.finditer(r"a\d","6a8ghjkasda3asdaa8")
print(r) 

在这个打印结果当中,第一个打印出来的是字典,第二个是迭代器对象。

那我们应该怎么获取迭代器当中的数据呢?

首先,使用循环。

# 方式一
for obj in r:
    print(obj)
    print(obj.group())  # 获取Match对象的文本内容
# <re.Match object; span=(1, 3), match='a8'>
# a8
# <re.Match object; span=(10, 12), match='a3'>
# a3
# <re.Match object; span=(16, 18), match='a8'>
# a8

方式二,使用next.

# 方式二
print(next(r)) # <re.Match object; span=(1, 3), match='a8'>
print(next(r)) # <re.Match object; span=(10, 12), match='a3'>
print(next(r)) # <re.Match object; span=(16, 18), match='a8'>
while True:
    try:
        obj=next(r)
        print(obj.group())
    except StopIteration as e:
        # 如果出现异常,则说明迭代器中的元素已经获取完毕
        break
# <re.Match object; span=(1, 3), match='a8'>
# <re.Match object; span=(10, 12), match='a3'>
# <re.Match object; span=(16, 18), match='a8'>

 接下来,我们来说一下split(),用正则指定的规则分割指定字符串,返回一个列表。

str1='one1two1three1four'
l1 = str1.split("1") # 字符串.split(分隔符),返回一个列表
print(l1) # ['one', 'two', 'three', 'four']

str1='one1two2three3four'
l1=re.split(r'\d+',str1) # re.split(正则分割符,字符串)
print(l1) # ['one', 'two', 'three', 'four']

l1=re.split(r'\d+',str1,2) # re.split(正则分割符,字符串,次数)
print(l1) # ['one', 'two', 'three3four']

 我们接下来讲一下sub和subn

sub是将正则匹配到的子字符串用指定字符串进行替换

str1="one111two111three111four"
l1=str1.replace("111","-")
print(l1) # one-two-three-four

# 可以指定替换的次数
str2="one31324two46465three4651four"
l1=re.sub(r"\d+","-",str2)
print(l1) # one-two-three-four

str2="one31324two46465three4651four"
l1=re.sub(r"\d+","-",str2,2)
print(l1) # one-two-three4651four

而subn返回的是一个元组,格式:(新字符串,替换的次数)

str2="one31324two46465three4651four"
l1=re.subn(r"\d+","-",str2,2)
print(l1) # ('one-two-three4651four', 2)

str2="one31324two46465three4651four"
l1=re.subn(r"\d+","-",str2)
print(l1) # ('one-two-three-four', 3)

接下来,我们说一下match,search,findall之间的区别

r1=re.match(r"\d+",'as1das2')
print(r1)   # None 从左往右匹配
r1=re.search(r"\d+",'as1das2')
print(r1) # <re.Match object; span=(2, 3), match='1'>
r1=re.findall(r"\d+",'as1das2')
print(r1)  # ['1', '2']

 注意,在正则中不要随便使用空格

print(re.search(r"\d+[a-z]+","3sdaasda-dasdad4")) # \d+ 数字可以出现一个或者多个
print(re.search(r"\d + [a-z]+","3sdaasda-dasdad4")) # \d +空格可以出现一个或者多个

flags的用法

re.I表示不区分大小写

# # flags的用法
# # re.I表示不区分大小写
print(re.split(r"a","dashjkhadAdashjkdkajaHJKHKHJAdashjkdh",re.I))
# 为了区分flasg,尽量使用关键字参数的方式给flags传参
print(re.split(r"a","dashjkhadAdashjkdkajaHJKHKHJAdashjkdh",flags=re.I))

 好了,我们今天的文章就到这里,我们明天再见。


网站公告

今日签到

点亮在社区的每一天
去签到