为了账号安全,请及时绑定邮箱和手机立即绑定

迷之语法 (^{}[]$-?)——Python正则表达式

基础篇?

> 正则表达式是一个特殊的字符序列,研究的是一个字符串是否与我们所设定的字符序列相匹配
> 它可以实现快速检索文本,实现一些替换文本的操作
> 使用场景举例:
> 1.检查一串数字是否是电话号码
> 2.检查一个字符串是否符合email标准
> 3.把一个文本里指定的单词替换为另一个单词

例.判断字符串是否包含Python(不用正则表达式,基于Python内置的函数)

a = 'C|C++|Java|C#|Python|Javascript'
#a.index('Python') > -1 为True时包含
print(a.index('Python'))
a.index('Python') > -1
print ('Python' in a)

图片描述
但是内置函数的表达方式有限
我们可以用Python的正则表达式模块re

re的findall()函数
findall()的参数:
re.findall(‘pattern’,‘string’) :
pattern为参与匹配的正则表达式
string为需要被匹配的字符串
图片描述
用re实现简单搜索功能
图片描述
以上用的是常量,没有体现匹配规则,而正则表达式重要的是应用于规则

Demo:提取字符串a中的所有数字,不使用for-in循环

#import re 
a = 'C0C++7Java8C#9Python6Javascript'
r = re.findall('\d',a)
print(r)
#正则表达式中'\d'表示数字

图片描述

重点

正则表达式的表示方式:
1.普通字符:举例:‘Python’
2.元字符:举例:’\d’

常见的元字符:
图片描述

Demo:提取字符串a中的所有非数字

import re 
a = 'C0C++7Java8C#9Python6Javascript'
r = re.findall('\D',a)
print(r)

图片描述

CH1.字符集:

Demo:6个单词中,找出中间字母是’c’或’f’的单词,关键点是’或’

import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('acc',s)
print(r)

图片描述
优化:需要抽象化’c’和’f’ ,用’[ ]'抽象
’a[cf]c’:普通字符’a’和’c’用来定义边界

import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[cf]c',s)
print(r)

图片描述

import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('[cf]',s)
print(r)

图片描述
出现在中括号‘[ ]’里的字符是‘或’关系

import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[cfd]c',s)
print(r)

图片描述

Demo:6个单词中,找出中间字母不是’c’,‘f’,’d’的单词

表示否定关系:[^ + 字符]


import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[^cfd]c',s)
print(r)

图片描述
Demo:列出匹配范围 :6个单词中,找出中间字母是’c’~'f’的单词

import re 
s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[c-f]c',s)
print(r)

图片描述

CH2.概括字符集

’/d’就是概括字符集,它可以概括所有的阿拉伯数字

import re 
a = 'python1111java&678php'
r = re.findall('\w',a)
print(r)

图片描述

’\w’只能匹配字符集中的26个单词字符,数字,以及下划线

import re 
a = 'python1111java&678php__'
r = re.findall('[A-Za-z0-9_]',a)
print(r)

图片描述
’\w’ == '[A-Za-z0-9_]'
’\W’刚好相反

Demo:
import re 
a = 'python1111java&678php__'
r = re.findall('\W',a)
print(r)

图片描述

#加入一个’\n’试试
Demo:
import re 
a = 'python1111java&678php__\n'
r = re.findall('\W',a)
print(r)

图片描述

CH3.数量词

之前的都是匹配单个字符
思考一下,如何匹配成组的字符

import re 
a = 'python1111java&678php__\n'
r = re.findall('[a-z][a-z][a-z]',a)
print(r)

图片描述
新的方式:在’{ }’中添加数字

import re 
a = 'python1111java&678php__\n'
r = re.findall('[a-z]{3}',a)
print(r)

图片描述
Demo:
如何完整输出:[‘python’,‘java’,‘php’]
解决方案:python有6个字符,java有4个字符,php有3个字符
字符数量的范围是3到6,{3,6}

import re 
a = 'python1111java&678php__\n'
r = re.findall('[a-z]{3,6}',a)
print(r)

图片描述

CH4.贪婪与非贪婪

贪婪:

mport re 
a = 'python1111java&678php__\n'
r = re.findall('[a-z]{3,6}',a)
print(r)

’[a-z]{3,6}’:Python会尽可能取里面最大的数
如果Python是按最小的取
那么第一个输出的字符串是:’pyt’

测试一下:

import re 
a = 'pythonscala1111java&678php__\n'
r = re.findall('[a-z]{3,6}',a)
print(r)

图片描述

非贪婪的表示方式:在表达式后面加一个”?”

import re 
a = 'pythonscala1111java&678php__\n'
r = re.findall('[a-z]{3,6}?',a)
print(r)

图片描述

CH5.匹配0次,1次或者无限次

字符’ * ’:匹配’ * ’前面的字符0次或者无限多次

Demo:
import re 
a = 'pytho0python1pythonn2'
r = re.findall('python*',a)
print(r)

图片描述
’ * ’前面的’n’可以出现0次或者无限多次

’ + ’前面的’n’可以出现1次或者无限多次


import re 
a = 'pytho0python1pythonn2'
r = re.findall('python+',a)
print(r)

图片描述
字符’?’:匹配’?’前面的字符0次或者1次

import re 
a = 'pytho0python1pythonn2'
r = re.findall('python?',a)
print(r)

图片描述
思考:第三个’python’出现的原因相当于’?’去掉了离它最近的一个n
所以’?’可以用来进行去重的操作

CH6.边界匹配

Demo:
研究QQ号是否符合要求
要求:大小在4~8位

import re 
qq = '101'
r = re.findall('\d{4,8}',qq)
print(r)

问题:大于8位的也匹配成功了


import re 
qq = '1000000001'
r = re.findall('\d{4,8}',qq)
print(r)

图片描述

正确的边界匹配:


import re 
qq = '1000000001'
r = re.findall('^\d{4,8}$',qq)
print(r)

图片描述

因为:
’^’表示从字符串开始的位置匹配
‘$’表示从字符串末尾开始匹配


Demo:
import re 
qq = '1000000001'
r = re.findall('^000',qq)
print(r)

图片描述

import re 
qq = '1000000001'
r = re.findall('000',qq)
print(r)

图片描述

CH7.组:一个’( )’对应一组

import re 
a = 'PythonPythonPythonPythonPython'
r = re.findall('(Python){4}',a)
print(r)

图片描述
‘[ ]’里的字符是’或’关系:里面的匹配条件可以部分满足
‘()’里的字符是’且’关系:里面的匹配条件必须全部满足

CH8.匹配模式

Re.findall(参数1,参数2,flag)
Flag:匹配参数

import re 
a = 'PythonC#JavaPHP'
r = re.findall('c#',a)
print(r)

图片描述

import re 
a = 'PythonC#JavaPHP'
r = re.findall('c#',a,re.I)
print(r)

图片描述

Flag = re.I:忽略字符串的大小写
多个Flag之间用’|’分隔

CH9.re.sub正则传递——查找字符串成功后替换字符串

Demo:把匹配到的’C#’换成’Go’


import re 
a = 'PythonC#JavaPHP'
r = re.sub('C#','Go',a)
print(r)

图片描述

Re.sub:count = 0 :无限次替换 ,count = 1 :只替换1次

import re 
a = 'PythonC#JavaC#PHP'
r = re.sub('C#','Go',a,0)
print(r)

图片描述

import re 
a = 'PythonC#JavaC#PHP'
r = re.sub('C#','Go',a,1)
print(r)

图片描述

Demo : 如果满足匹配条件,就执行convert函数

import re 
language = 'PythonC#JavaC#PHPC#'
def convert(value):
	print(value)
r = re.sub('C#',convert,language)
print(r)

图片描述

import re 
language = 'PythonC#JavaC#PHPC#'
def convert(value):
	matched = value.group()
	return '!!'+matched+'!!'
	
r = re.sub('C#',convert,language)
print(r)

图片描述

import re 
s = 'A8C3721D86'
def convert(value):
	matched = value.group()
	if int(matched) >= 6:
		return '9'
	else :
		return '0'

r = re.sub('\d',convert,s)
#每找到一个数字,调用一次convert函数
print(r)

图片描述

CH10:Group分组

import re 
s = 'life is short,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.group(0))
print(r.group(1))
print(r.group(2))

图片描述
补充篇? 有基础的可以之间跳到这里?
Python正则表达式的一些小知识点:
1.正则表达式的三个一般字符:
“.”:匹配任意单个字符(不包括换行符\n),a.b可以匹配:abc,aic,a&c等
“\”:转义字符,把有特殊含义的字符转换成字面意思,例如”.”字符是匹配任意的单个字符,但有时不需要这个功能,只想让它代表一个点,”.”就可以匹配”.”了
#建议使用Python的r前缀,就不用考虑转义的问题了
2.非贪心算法(.*?):

import re 
a = 'xxIxxjshdxxlovexxsffaxxpythonxxx'
infos = re.findall('xx(.*?)xx',a)
print(infos)

图片描述
3.findall&search:

findall把符合条件的都匹配了,以列表的形式返回结果
search只匹配符合条件的第一条内容,返回一个正则表达式对象


import re 
a = 'one1two2three3'
infos = re.findall('\d+',a)
print(infos)
print(infos.group())
print(infos.group(0))
print(infos.group(1))
print(infos.group(2))

图片描述


import re 
a = 'one1two2three3'
infos = re.search('\d+',a)
print(infos)
print(infos.group())
print(infos.group(0))
print(infos.group(1))
print(infos.group(2))

图片描述

4.sub函数__用于替换字符串中的匹配项
re.sub(pattern,repl,string,count =0,flags = 0)
Count:模式匹配后替换的最大次数,默认0表示替换所有的匹配

通过sub()函数去掉电话号码”123-4567-1234”中间的”-”。
Demo:

import re 
phone = '123-4567-1234'
new_phone = re.sub('\D','',phone)
print(new_phone)

图片描述

sub函数类似于str中的replace函数,但sub函数因为通过匹配正则表达式来替换字符串,因而比replace函数更灵活。
5.单词的边界
正则里面有2个特殊字符\b and \B来匹配单词的边界 :
\b 匹配的模式是一个单词的边界(不论这个单词的前面是有字符还是没有字符)
\B 匹配出现在一个单词中间的模式
例如:
the #匹配包含有’the’的字符串
\bthe #匹配任何以’the’开始的字符串
\bthe\b #仅仅匹配单词’the’
\Bthe #匹配任意包含’the’但不以’the’开头的单词
6.多选结构 &可选项元素
多选结构
我们需要匹配’grey’或者’gray’的时候,怎么办,可以用正则的[]来表示,gr[ea]y,表示先找到g,然后找到r,然后找到e或者a,最后是一个y

patt=re.compile(r’gr[ea]y’)
我们可以用’|‘来匹配任意子表达式,’|‘是一个非常简便的元字符,它的意思是"或",通过它我们能把不同的子表达式组合成一个总的表达式,
比如’am’|‘pm’就是能够同时匹配其中任意一个的正则表达式,回头再看上面的例子’gr[ea]y’,其实能写成’grey|gray’,或者’gr(e|a)y’

可选项元素
’?’ 表示可选项,问号跟在什么后面就表示什么是可选的
例如:6月4日,可能写成’June’也可以写成’Jun’,而且日期也有可能写作’fourth’或者’4th’或者4,这个时候就可以写成June?(fourth|4(th)?),代表了e是可选的,th是可选的,可有可无都表示4号


#设计一个正则来过滤一个字符串序列中的10到59
import re 
pattern = r'[1-5][0-9]'
lis = [10,20,30,40,2,3,59,60,'aa','3aaa']
match = re.findall(pattern,str(lis))
if match:
	print(match)

图片描述

#过滤正确的24小时时间制
import re 
time = '10:00,99:90,8:00,520:00,1314:00,14:00pm,5:xm,6,00,4654,8:0923:23pm,29:19:pm,23:59'
pattern = r'\b([01]?[0-9]|2[0-4])(:)([0-5][0-9])'
match   = re.findall(pattern,time)
if match:
	print([''.join(x) for x in match])

图片描述
参考教程:
《从零开始学Python网络爬虫》
https://coding.imooc.com/lesson/136.html#mid=7694

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消