python基础之坑爹正则表达式

概述

re模块就是python语言中的正则表达式,拆出来单独写一条blog是因为正则表达式本身就是比较庞大的知识,写具体些让自己以后方便查找。

IP:
^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
手机号:
^1[3|4|5|8][0-9]\d{8}$

由于在python中,“\”也被定义为转义字符,因此两个python中的“\”才能代表一个正则中的“\”,这就导致了大量的“\”重复。为了解决这一问题,python提供了原生字符的办法。也就是在字符串前面加上一个“r”,代表此字符串中的“\”可直接用于正则表达式,而不用再次转义。因此,请养成在python的正则表达式字符串的前面添加一个“r“的好习惯。

字符

字符匹配分为普通字符和元字符.

  • 大多数字符都会和自身匹配
  • 元字符,元字符在[]中没有特殊意义,元字符包括:
元字符 含义
. 匹配除换行符外的所有字符
\w 匹配字母或者数字或者下划线或汉字
\W 匹配任何非字母或数字或下划线,汉字
\s 匹配任意的空白符,相当于[ \t\n\r\f\v]
\S 匹配任意非空白字符
\d 匹配任意十进制数字
\D 匹配任意非数字字符
\b 匹配单词的开始或者结束,即单词和空格的位置,只是匹配字符串开头结尾及空格回车等的位置, 不会匹配空格符本身
^ 匹配字符串的开始
匹配字符串的结束
* 重复0次或更多次
+ 重复1次或多次
? 重复0次或1次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
[] 用来指定一个字符集和范围,字符可以单个列出,也可以用“-”号分隔的两个给定.字符来表示一个字符区间。例如,[abc] 将匹配"a", "b", 或 "c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致
\ 反斜杠跟后面的元字符,去除元字符的特殊功能;与普通字符一起,实现特殊功能.
() 分组功能

字符中需要注意的事项

  • 如果元字符存在于[]中的字符类中时,只有字符^,-,\有特殊含义.其他无特殊意义.例如:

例如,[akm\(]将匹配字符"a", "k", "m", 或 "\)" 中的任意一个;"$"通常用作元字符,但在字符类别里,其特性被除去,恢复成普通字符。

元字符 含义
\ 仍表示转义
- 表示范围
^ ^放在支付前面,表示非
  • *?,+?,??,{m,n}? 前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配,后面加个问号,将策略改为非贪婪,只匹配尽量少的RE,来个例子吧:
>>> re.findall(r"a(\d+?)","a23b") # 非贪婪模式
['2']
>>> re.findall(r"a(\d+)","a23b")
['23']
  • \b 就是用在你匹配整个单词的时候。 如果不是整个单词就不匹配。 你想匹

    配 I 的话,你知道,很多单词里都有I的,但我只想匹配I,就是“我”,这个时

    候用 \bI\b

re模块中的函数

函数 描述 返回值
compile(pattern[, flags]) 根据包含正则表达式的字符串创建模式对象 re模块的对象
search(pattern, string[, flags]) 在字符串中寻找模式 第一个匹配到或者None
match(pattern, string[, flags]) 在字符串的开始处匹配模式 在字符串开头匹配的对象或者None
split(pattern, string[, maxsplit=0,flags]) 根据模式的匹配项来分割字符串 分割后的字符串列表
findall(pattern, string,flags) 列出字符串中模式的所有匹配项 所有匹配到的字符串列表
sub(pat,repl, string[,count=0,flags]) 将字符串中所有的pat的匹配项用repl替换 完成替换后的新字符串
finditer(pattern, string,flags) 将所有匹配到的项生成一个迭代器 所有匹配到的字符串组成的迭代器
subn(pat,repl, string[,count=0,flags]) 在替换字符串后,同时报告替换的次数 完成替换后的新字符串以及替换的次数,返回值为元组数据
escape(string) 将字符串中所有特殊正则表达式字符串转义 转义后的字符串
purge(pattern) 清空正则表达式
template(pattern[,flags]) 编译一个匹配模板 模式对象
fullmatch(pattern, string[, flags]) match函数的全字符串匹配版本 类似match的返回值

compile

将正则表达式转换为模式对象,提高工作效率。使用compile转换后,以后在每次模式使用时直接调用即可!经过compile转换的正则也能使用普通的re函数。

import re
res=re.compile(r'abc')
print(res.match('abcde'))
print(res.match('abcd123').group)
print(res.match('abcd123').group())

输出:

<_sre.SRE_Match object; span=(0, 3), match='abc'>
<built-in method group of _sre.SRE_Match object at 0x0000016911B395E0>
abc

从输出的结果我们可以看出来,compile处理后,返回的是re对象。事实上,compile是在调用match,findall函数之前默认优先编译的一步,所有我们可以在重复调用的某匹配的时候,可先将re.compile赋值于一个变量。

match

match对指定字符串的开头进行匹配,匹配成功后返回一个match的object,如果匹配不成功返回None!

res=re.match(r'abc','123')
print(res)
res1=re.match(r'abc','abc23')
print(res1)
print(res1.start())
print(res1.end())
print(res1.span())
print(res1.group())

out:

None
<_sre.SRE_Match object; span=(0, 3), match='abc'>
0
3
(0, 3)
abc

out中span表示匹配到数字的下标范围,从0到2,所以与列表、字典中取值是相同的

group()是用来直接查看匹配的结果的

search

search用来在指定字符串中查找,返回值为第一个匹配到的字符串

使用方法和match类似

res=re.search(r'abc','123abcsdfsdfsdfabc')
print(res.group())
print(res.start())
print(res.end())
print(res.span())

结果:

abc
3
6
(3, 6)

findall

findall是搜索指定字符串中的所有指定匹配项,返回值为一个列表,如果没有匹配项,那么返回的是一个空列表,而且,findall不需要group()

res=re.findall(r'efg','12efg,sdf,efgsdfsd')
print(res)
res1=re.findall(r'efg','12asdfasdfasdf')
print(res1)

out:

['efg', 'efg']
[]

split

split类似字符串中的分割,用来指定字符串为分隔符,将匹配目标分割成列表形式。而且split有一个maxsplit的参数,用来指定分割的次数

s='1*8+2-6*-10'
res=re.split(r'[\+\-\*\/]',s)
print(res)
res1=re.split(r'[\+\-\*\/]',s,maxsplit=3)
print(res1)

out:

['1', '8', '2', '6', '', '10'] #1
['1', '8', '2', '6*-10']

注意看结果,#1标志中,为什么第一行的结果,索引-2会是一个空值呢,,是因为"6*-10",将*切割,10前面的负号和星号中间为空值

而利用re模块中牛逼哄哄的分组功能,能将分割出来的字符串包括分隔符都加入列表中。来看下:

s='1*8+2-6*-10'
res2=re.split(r'([\+\-\*\/])',s)
print(res2)

out:

['1', '*', '8', '+', '2', '-', '6', '*', '', '-', '10']

sub

sub类似字符串中的replace功能,用指定的内容替换匹配到的字符或字符串,同时也可以指定替换次数,使用count= 来指定,或者直接数字也可

s='hello,I am cc!What the fuck day!'
res=re.sub(r'a','xxx',s)
print(res)
res2=re.sub(r'a','xxx',s,count=2)
print(res2)

out:

hello,I xxxm cc!Whxxxt the fuck dxxxy!
hello,I xxxm cc!Whxxxt the fuck day!

subn

看代码吧,同上,只不过比sub多了替换次数,返回值为元组

s='hello,I am cc!What the fuck day!'
res=re.subn(r'a','xxx',s)
print(res)
print(type(res))

out:

('hello,I xxxm cc!Whxxxt the fuck dxxxy!', 3)
<class 'tuple'>

group和groups

groups返回元组,group返回的是字符串

直接看代码吧:

a = "123abc456"
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).groups())
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).group())
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).group(0))
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).group(1))
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).group(2))
print(re.search(r"([0-9]*)([a-z]*)([0-9]*)", a).group(3))

out:

('123', 'abc', '456')
123abc456
123abc456
123
abc
456

flag编译标识

flag为re匹配时的匹配模式,有X I M S A L U,7种模式.

标识符 全拼 作用
I IGNORECASE 忽略大小写
L LOCALE 使\w, \W, \b, \B, \d, \D依赖于本地设置
M MULTILINE 让正则表达式的^和$符号可以适应多行模式的字符串
X VERBOSE 注释模式
A ASCII 对于字符串,使得\w, \W, \b, \B, \d, \D只匹配ACSII码字符集,而不是整个Unicode字符集(默认);对于bytes模式,这个编译标志是默认设置,不需要特别指定。
S DOTALL 使 "." 特殊字符完全匹配任何字符,包括换行;没有这个标志, "." 匹配除了换行外的任何字符
U UNICODE 兼容模式。在字符串模式下被忽略(默认模式),在字节模式下被禁止

M说明下:

s='\n123\n'
res=re.search(r'^123',s)
print(res.group())

这么执行会报错.

但如果使用下面re.M就会正常:

res1=re.search(r'^123',s,re.M)
print(res1.group())

分组

先上例子:

>>> p = re.compile('(a(b)c)d')
>>> m = p.match('abcd')
>>> m.group(0)
'abcd'
>>> m.group(1)
'abc'
>>> m.group(2)
'b'

分组是在re中比较牛逼的东西,功能:去已经匹配到的结果中再提取数据,相当于二次过滤.

提取分组结果使用group groups groupdict

先来看下无分组的结果:

s='abc23434efdabceab'
res=re.match(r'a\w+',s)
print(res.group())
print(res.groups())
print(res.groupdict())

out:


abc23434efdabceab
()
{}

再来看有分组的:

s='abc23434efdabceab2'
res=re.match(r'a(\w+).*(?P<name>\d)$',s)
print(res.group())
print(res.groups())
print(res.groupdict())

out:

abc23434efdabceab2
('bc23434efdabceab', '2')
{'name': '2'}

解释下:匹配时是按r''中的整体去匹配的,第一次匹配完之后,然后再用括号去匹配.有两个括号,那就是从匹配到的结果中,再过滤出两个匹配的结果.再看个例子:


s='abc23434efdabceab2'
res=re.search(r'a(\w+).*(?P<name>\d)$',s)
print(res)
print(res.group())
print(res.group(0))
print(res.group(1))
print(res.group(2))
print(res.groups())
print(res.groupdict())

out:

<_sre.SRE_Match object; span=(0, 18), match='abc23434efdabceab2'>
abc23434efdabceab2
abc23434efdabceab2
bc23434efdabceab
2
('bc23434efdabceab', '2')
{'name': '2'}

可以看出来,group 结果的字符串,groups是元组,groupdict是字典.在group结果中,获取分组结果时,取括号的索引即可,第几个就是group(几),group(0)是第一次匹配出的结果本身

findall,split中的分组有歧义

origin = "hello alex bcd alex lge alex acd 19"
r = re.split("a(le)x", origin)
print(r)

out:

['hello ', 'le', ' bcd ', 'le', ' lge ', 'le', ' acd 19']
s='abc1223434efdabc34121224eabc12'
res=re.findall(r'a(bc)(12)*',s)
print(res)

out:

[('bc', '12'), ('bc', ''), ('bc', '12')]

sub中没有分组的概念

s='abc1223434efdabc34121224eabc12'
res=re.sub(r'a(bc)(12)*','xxx',s)
print(res)

out:

xxx23434efdxxx34121224exxx

看来并没有什么乱用!

python基础之坑爹正则表达式的更多相关文章

  1. python基础之 re(正则表达式)模块学习

    今天学习了Python中有关正则表达式的知识.关于正则表达式的语法,不作过多解释,网上有许多学习的资料.这里主要介绍Python中常用的正则表达式处理函数. re.match re.match 尝试从 ...

  2. Python基础:28正则表达式

    一:概述 正则表达式(RE)为高级文本模式匹配,以及搜索-替代等功能提供了基础.正则表达式(RE)是一些由字符和特殊符号组成的字符串,它们能匹配多个字符串.Python通过标准库的re模块支持正则表达 ...

  3. 【笔记】Python基础七:正则表达式re模块

    一,介绍 正则表达式(RE)是一种小型的,高度专业化的编程语言,在python中它内嵌在python中,并通过re模块实现.正则表达式模式被编译成一系列的字节码,然后由C编写的匹配引擎执行. 字符匹配 ...

  4. python基础学习笔记——正则表达式

    1.什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...

  5. python 基础(十四) 正则表达式

    正则表达式 概念: 正则匹配就是一个模糊的匹配 只要符合我的匹配规则 就会认为是正确的数据(精确的匹配) 1.[] #代表原子表把想要匹配的内容写入原子表中   匹配包含的任意一位字符 [a]     ...

  6. python基础:8.正则表达式

    1.概念 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. re模块的常见方法: ...

  7. python基础知识(正则表达式)

    使用正则表示式分割字符串 split() re.split(pattern,string,[maxsplit],[flags]) re.split(指定一个模式字符串,要匹配的字符串,最大的拆分次数, ...

  8. python基础-6.2正则表达式,计算器练习

    content = "1-2*((60-30+(1-40/5*5+3-2*5/3)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))&q ...

  9. Python基础之 正则表达式指南

    本文介绍了Python对于正则表达式的支持,包括正则表达式基础以及Python正则表达式标准库的完整介绍及使用示例.本文的内容不包括如何编写高效的正则表达式.如何优化正则表达式,这些主题请查看其他教程 ...

随机推荐

  1. 【搜索/tarjan找环】zznu-简单环路

    简单环路 题目描述 有一个N x M 大小的地图,地图中的每个单元包含一个大写字母. 若两个相邻的(这里的相邻指“上下左右”相邻)点上的字母相同,我们可以用线段连接这两个点. 若存在一个包含同一字母的 ...

  2. element-ui upload组件 onchange事件 传自定义参数

     <el-upload     class="upload-demo"     list-type="picture"     accept=" ...

  3. TG2

    1,什么滑动窗口? 2,这人讲的不行还是我的问题.. 3,搞得我都想睡觉了 4,1904,不停扫,输出最高的高度 一个差分的过程,先加上再减去,但是要维护一个最值 什么动态开点(只能用线段树并且内存很 ...

  4. LeetCode按照解题方法分类题目

    解题方法分类 1. 滑动窗口. 2. 双指针. 3. 快慢指针. 4. 区间合并. 5. 循环排序. 6. 原地反转链表. 7. 树上的BFS. 8. 树上的DFS. 9. 双堆. 10. 子集. 1 ...

  5. 078_使用 egrep 过滤 MAC 地址

    #!/bin/bash#MAC 地址由 16 进制组成,如 AA:BB:CC:DD:EE:FF#[0-9a-fA-F]{2}表示一段十六进制数值,{5}表示连续出现 5 组前置:的十六进制egrep ...

  6. Cogs 329. K- 联赛(最大流)

    K- 联赛 ★★★ 输入文件:kleague.in 输出文件:kleague.out 简单对比 时间限制:1 s 内存限制:32 MB [问题描述] K- 联赛职业足球俱乐部的球迷们都是有组织的训练有 ...

  7. 「学习笔记」FFT及NTT入门知识

    前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...

  8. 4、wordcount程序原理剖析及Spark架构原理

    一.wordcount程序原理深度剖析 二.Spark架构原理 1.

  9. ROS常用工具

    先将这个package放到工作空间的 src 目录中, 链接:点击打开链接 密码:u98p 然后在工作空间中加入依赖, rosdep install --from-paths src --ignore ...

  10. Python基础之可接受任意数量参数的函数

    1. 可接受任意数量位置参数的函数 为了能让一个函数接受任意数量的位置参数,可以在参数部分使用“*”. def avg(first, *rest): return (first + sum(rest) ...