re 模块 & 正则表达式
re模块与正则表达式之间的关系:
正则表达式不是python独有的
所有的编程语言都可以使用正则,它是一门独立的语言
如果想在python中使用,就必须依赖于re模块
正则:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。用来筛选字符串中特定的内容;可在爬虫和数据分析中使用。
注:只要是以reg...开头,基本上都是与正则有关
PS:在线测试工具 http://tool.chinaz.com/regex/
接下来就是正则表达式的表达式了:
1.字符
元字符 匹配内容 |
. 匹配除换行符以外的任意字符 |
\w 匹配所有的数字、字母、下划线 |
\s 匹配任意的空白符 |
\d 匹配数字 |
\n 匹配一个换行符 |
\t 匹配一个制表符 |
\b 匹配一个单词的结尾 |
^ 匹配字符串的开始 |
$ 匹配字符串的结尾 |
\W 匹配非字母或数字或下划线 |
\D 匹配非数字 |
\S 匹配非空白符 |
a|b 匹配字符a或字符b |
() 匹配括号内的表达式,也表示一个组 |
[...] 匹配字符组中的字符 |
[^...] 匹配除了字符组中字符的所有字符 |
2.量词
* 重复0次或更多次 |
+ 重复1次或更多次 |
? 重复0次或1次 |
{n} 重复n次 |
{n,} 重复n次或更多次 |
{n,m} 重复n次到m次 |
3.字符组
如:[0123456789] 表示可以筛选出内容中所有的单个数字 可简写为[0-9]
[a-z] 表示可以筛选出内容中所有小写字母a到z单个字母
[A-Z] 表示可以筛选出内容中所有大写字母A到Z单个字母
此外,还可以组合使用,中间不空格。如:
[0-9a-z] 表示可以筛选出内容中所有的单个数字以及a-z单个字母
************************************************************
- 字符组[]:[]里面的表达式 都是 或 的关系 是字符串,连着的
- ^与$符连用,会精准限制匹配的内容,两者中间写什么,匹配的字符串就必须是什么,多一个也不想少一个也不行
- abc|ab 一定要将长的放在前面
- ^ 直接写在外面---限制字符串的开头;而[^] 除了[]写的字符 其他都要
- 正则在匹配的时候默认都是贪婪匹配(尽量匹配多的),你可以通过在量词后面加上一个?就可以将贪婪匹配变成非贪婪匹配(惰性匹配)
- 量词必须跟在正则符号的后面,且只能够限制紧挨着它的那一个正则符号
- 当多个正则符号需要重复多次的时候或者当做一个整体进行其他操作,那么可以分组的形式;分组在正则的语法中就是()
如身份证号的判断:^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
分析过程:①以^开头以$结尾,中间内容被精准限制
②分组(),表示()里面需要当做一个整体
③|,表示|两边的内容都可以筛选到,而且将长的放在左边
④|左边的正则表达式表示 以数字1-9开头 中间接16个数字 最后一位可以是0-9或小写字母x任意一个 一共18位
⑤|右边的正则表达式表示 以数字1-9开头 后面接14个数字 一共15位
************************************************************
补充:
转义符: \
在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的"\n"而不是"换行符"就需要对"\"进行转义,变成'\\'。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。
所以如果匹配一次"\n",字符串中要写成'\\n',那么正则里就要写成"\\\\n",这样就太麻烦了。这个时候我们就用到了r'\n'这个概念,此时的正则是r'\\n'就可以了。
几个常用的非贪婪匹配Pattern:量词后面加上一个?就可以将贪婪匹配变成非贪婪匹配(惰性匹配)
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法:
.是任意字符 *是取0至无无限长度 ?是非贪婪模式
合在一起就是 取尽量少的任意字符
一般写.*?x 表示取前面任意长度的字符出现,直到一个x出现
re模块的常用方法:
首先在py文件中导入模块 import re
re模块的调用方式主要有三种:findall / search / match findall / search / match('正则表达式','带匹配的字符串')
import re ret = re.findall('a', 'eva egon yuan') # 返回所有满足匹配条件的结果,放在列表里 print(ret) #结果 : ['a', 'a'] ret = re.search('a', 'eva egon yuan').group() print(ret) #结果 : 'a' # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。 ret = re.match('a', 'abc').group() # 同search,不过尽在字符串开始处进行匹配 print(ret) #结果 : 'a'
此外,还有split :
ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd']
sub : sub('正则表达式','新的内容','待替换的字符串',n)
ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个 print(ret) #evaHegon4yuan4
subn :
ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret)
compile :
obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #结果 : 123
finditer :
import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一个结果 print(next(ret).group()) #查看第二个结果 print([i.group() for i in ret]) #查看剩余的结果
注意:优先级查询
1. findall的优先级查询
import re ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可 ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') # ?:可以取消这种优先级查询权限 print(ret) # ['www.oldboy.com']
2. split的优先级查询
ret=re.split("\d+","eva3egon4yuan") print(ret) #结果 : ['eva', 'egon', 'yuan'] ret=re.split("(\d+)","eva3egon4yuan") print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan'] #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。
给某一个正则起别名:!!!!
import re res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199812067023') res = re.search('^[1-9](?P<password>\d{14})(?P<username>\d{2}[0-9x])?$','110105199812067023') # 固定格式: ? + 大写的P + <名字>