🌈个人主页:羽晨同学
💫个人格言:“成为自己未来的主人~”
我们这个文章所讲述的,也是数据分析的基础文章,正则表达式
首先,我们在开始之前,引出一个问题。也是我们接下来想要解决的问题。
那就是,我们应该怎么判断合适的QQ号。
一个合适的QQ号应该包括下面的几个部分:
- 全数字
- 位数 5-11
- 开头不能为0
我们先给大家实现一下这个解决这个问题的代码,稍后再给大家讲解一下其中的原理。
def check_qq(qq):return qq.isdigit() and len(qq) in range(5,12) and not qq.startswith('0')
qq = '91915235'
res = check_qq(qq)
print(res)
这个是用我们之前所熟悉的代码来实现这个功能,这个应该不用太仔细解析,大家可以先好好看看。
我们接下来重点看用正则实现这个功能的部分。
def check_qq(qq):return qq.isdigit() and len(qq) in range(5,12) and not qq.startswith('0')
qq = '919152305'
res = check_qq(qq)
print(res)import re
def check_qq1(qq):r=re.match(r"^[1-9]\d{4,10}$",qq)return True if r else False
if __name__ =='__main__':qq='0543265'r1=check_qq1(qq)print(r1)r2=check_qq(qq)print(r2)
下面的部分就是用正则表达式实现的。其中包含了很多的知识点,这个需要我们慢慢来进行分析。
首先,我们先来看一下结果。
这两个的结果是完全相同的。
单字符匹配
单字符匹配就是说,无论[]里面包含了多少字符,只能匹配其中的一位。
.: 默认情况下,匹配除了换行符以外的任意字符。
match():如果匹配上,则返回match对象,如果未匹配上,则返回None
我们来看一下例子。
import re
r=re.match(r'.','\n')
print(r)
r1=re.match(r'.','5')
print(r1)
这个例子就可以很好的解释我们刚才所看到的。
后期在爬虫中,要爬取网页内容,网页中有大量的换行,则我们需要设置flags=re.DOTALL
r=re.match(r'.','\n',flags=re.DOTALL)
我们再来看下一个例子
import re
r1=re.match(r"[0-9a-zA-Z]","F")
print(r1)
r2=re.match(r"[gbk]","b")
print(r2)
r3=re.match(r"[^gbk]","b")
print(r3)
我们可以看到,第一个和第二个都匹配到了,但是第三个没有,这是因为^只能匹配第一个。第一个不符合,就返回了None
我们来看下一个例子:
import re
r1=re.match(r"[0-9a-zA-Z]","F")
print(r1)
r2=re.match(r"\w","a")
print(r2)r3=re.match(r"\s"," ")
print(r3)
r4=re.match(r"\s","\n")
print(r4)
在这段代码当中,我们可以看到的是,\s无论是空格还是换行符都可以匹配到。
数量词匹配
我们先来看一下示例代码
import re
print(re.match(r'\d\d\d\d',"4567"))
这个就是我们上面所讲到的单字符匹配,一共四个\d,所以可以匹配四个数字
那么,这个有更多的使用方式吗,答案是,有的。
我们来看下面的三种调用方法:
import re
# print(re.match(r'\d\d\d\d',"4567"))
print(re.match(r'\d{4}',"4654"))
print(re.match(r'\d{4,}',"464564654"))
print(re.match(r"\d{4,10}","46545497974564654654645"))
第一种是恰好调用四个,第二个是最少四个,第三个是四个到10个
我们可以来看一下打印出来的结果。
我们再来看下一个例子:
import re
print(re.match(r'a?','aaaaaaaaaaaaaaaa'))
print(re.match(r'a+',''))
print(re.match(r'a*',''))
第一个表示单个字符,第二个表示1个或无数个,最后一个表示0个或无数个
我们再来看下一个例子:
import re
print(re.search(r'a?','aaaaaaaaaaaa'))
print(re.search(r'a+','aaa'))
print(re.search(r'a*','aaaa'))
下面使我们运行出来的结果。
其实search的底层调用的就是match,和match相似的是,调用成功的话,返回调用对象,如果不匹配的话,返回None。
我们再来看一下下一种情况:
import re
print(re.findall(r'a?','aaaaaaaaa'))
print(re.findall(r'a+','aaaaaaaaa'))
print(re.findall(r'a*','aaaaaaaaa'))
下面是我们运行的结果。
findall()在源字符串中从左向右查找,将所有符合条件的子字符串全部查找出来 。
边界匹配
我们来看下一种情况
^和$匹配的是整个字符串的行首或行尾
import re
print(re.findall(r"^this","this is a text\nthis is a text\nthis is a text\n"))
print(re.findall(r"text$","this is a text\nthis is a text\nthis is a text\n"))
我们再来看一下打印出来的结果。
为什么只会打印出来一个呢?
这是因为默认情况下,即使字符串中有换行符,也是默认的单行模式。
我们可以设置在多行模式下面看一下:
import re
print(re.findall(r"^this","this is a text\nthis is a text\nthis is a text\n",flags=re.M))
print(re.findall(r"text$","this is a text\nthis is a text\nthis is a text\n",flags=re.M))
我们在后面加上一个re.M,就变成了单行模式,对应的,结果也会发生变化。
我们也可以搜索多行模式下面的第一个和最后一个,看下面这个代码
import re
print(re.findall(r"\Athis","this is a text\nthis is a text\nthis is a text\n",flags=re.M))
print(re.findall(r"text\Z","this is a text\nthis is a text\nthis is a text",flags=re.M))
在这种情况下,我们搜索到的也是一个
贪婪匹配和非贪婪匹配
?非贪婪匹配
+ * 贪婪匹配
首先,我们来看一下下面这个代码:
import re
print(re.findall(r'a?','aaaaaaaaaaaaa')) #0个或者一个
print(re.findall(r'a+','aaaaaaaaaaaaa')) #一个或者多个
print(re.findall(r'a*','aaaaaaaaaaaaa')) #0个或者多个
这个其实就是我们之前所提到过的贪婪匹配和非贪婪匹配。
更多的非贪婪匹配和贪婪匹配的内容,我们在下一篇文章中说,大家,明天见。