基础篇?
> 正则表达式是一个特殊的字符序列,研究的是一个字符串是否与我们所设定的字符序列相匹配
> 它可以实现快速检索文本,实现一些替换文本的操作
> 使用场景举例:
> 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
共同学习,写下你的评论
评论加载中...
作者其他优质文章