python之re模块
re模块
正则的特点
贪婪模式与非贪婪模式
import re
s="This is a number 234-235-22-423"
r=re.match(".+(\d+-\d+-\d+-\d+)",s)
print(r.group(1))
r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
print(r.group(1))
'''
4-235-22-423
234-235-22-423
'''
"""
总结:正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。
解决方式:非贪婪操作符“?”,这个操作符可以用在"*","+","?"的后面,要求正则匹配的越少越好。
"""
反斜杠的困扰
# 当使用反斜杠\,被系统转义时,我们可以使用r"\*******" 这样就不会被转义了。当然还有其他的方式,我这里就不列举了。本人推荐这种方法
常用的基础正则
1. \d 匹配数字 [0-9]
2. \D 匹配非数字 [^0-9]或者[^\d]
3. \s 匹配空白字符
4. \S 匹配非空白字符
5. \w 匹配字母,数字,下划线,中文
6. \W 匹配非字母,数字,下划线,中文
7. * 匹配前一个字符0次或多次
8. . 匹配任意字符(\n除外,在DOTALL模式中可以匹配换行符)
9. ? 匹配前一个字符0次或1次
10. + 匹配前一个字符1次或多次
11. ^ 以什么开头
12. $ 以什么结尾
13. {m,n} 匹配前一个字符n到m次
14. | 或
15. () 只需要括号内的内容
import re
s = "那违法挖#而 非挖而非aewfawef1安132123慰法万恶按而*无法埃尔文发违&faw法违法违法噶!让我给你哦啊降$123tq43t34y温哦下降为阿y34353763文哥阿尔瓦工价^位高阿文&哥奇偶位二极管"
# 1. 以"那违法"开头
res = re.findall("^那违法",s)
# 2. 以"极管"结尾
res = re.findall("极管$",s)
# 3. 匹配字母,数字,下划线,中文
res = re.findall("\w+",s)
# 4. 匹配数字
res = re.findall("\d+",s)
# 5. 匹配非数字
res = re.findall("\D+",s)
# 6. 匹配空字符
res = re.findall("\s+",s)
# 7. 匹配非空字符
res = re.findall("\S+",s)
更多详细的规则可以参考链接
re模块中常用功能函数(掌握)
1. findall()是直接在函数里书写规则,推荐使用
import re
string = "abceefefawef"
res = re.findall("匹配规则",string)
2. compile() 编写"规则"模板
import re
string = "hello world"
a = re.compile('^h.* (.*)') # 编写的规则模块
match = a.match(string)
print(match.group(1))
re.compile(strPattern[,flag])函数 ****
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。 第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M。另外,你也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的
下表是所有的正则匹配模式
标志 | 含义 |
---|---|
re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
re.I(IGNORECASE) | 使匹配对大小写不敏感 |
re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
re.M(MULTILINE) | 多行匹配,影响^和$ |
re.X(VERBOSE) | 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解 |
re.U | 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B |
3. match()函数,从开头匹配一个符合规则的字符串
# re.match(pattern,string[,flags])
# match(pattern, string, flags=0)
# pattern:正则模型
# string:要匹配的字符串
# falgs:匹配模式
# 注意:match()函数 与 search()函数基本是一样的功能,不一样的就是match()匹配字符串开始位置的一个符合规则的字符串,search()是在字符串全局匹配第一个合规则的字符串
import re
string = "hello egon bcd egon lge egon acd 19"
res = re.match('.*e.*d',string) # 从开头进行匹配,如果没有匹配到返回None
print(res)
res_two = re.match('^e.*(e.*d)',string) # None
print(res_two)
'''
<_sre.SRE_Match object; span=(0, 32), match='hello egon bcd egon lge egon acd'>
None
'''
4. group()分组函数
import re
string = "hello egon bcd egon lge egon acd 19"
a = re.match(".(.*9$)",string)
print(a.groups()) # 获取所有匹配到的分组结果,只拿出匹配到的字符串中
print(a.group(1)) # 获取第2个分组结果
print(a.group()) # 只要匹配上的都拿出来
print(a.groupdict()) # 获取模型中匹配到的分组结果,只拿除匹配到的字符串分组部分定义key的组结果
# 有两个分组定义了key
# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
# ?P<>定义组里匹配内容的key(键),<>里面写key名称,值就是匹配到的内容
r = re.search("a(?P<n1>\w+).*(?P<n2>\d)", origin)
print(r.group()) # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来
print(r.groups()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
print(r.groupdict()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
只对正则函数返回对象的有用
- group() # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来,有参取匹配到的第几个如2
- groups() # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
- groupdict() # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
5. search()函数
'''
search,浏览全部字符串,匹配第一符合规则的字符串,浏览整个字符串去匹配第一个,未匹配成功返回None
search(pattern, string, flags=0)
pattern: 正则模型
string : 要匹配的字符串
falgs : 匹配模式
注意:match()函数 与 search()函数基本是一样的功能,不一样的就是match()匹配字符串开始位置的一个符合规则的字符串,search()是在字符串全局匹配第一个合规则的字符串
'''
import re
# 无分组
origin = "hello alex bcd alex lge alex acd 19"
# search浏览全部字符串,匹配第一符合规则的字符串,浏览整个字符串去匹配第一个,未匹配成功返回None
r = re.search("a\w+", origin)
print(r.group()) # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来
print(r.groups()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
print(r.groupdict()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
'''
alex
()
{}
'''
# 有分组
# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
r = re.search("a(\w+).*(\d)", origin)
print(r.group()) # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来
print(r.groups()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
print(r.groupdict()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
'''
alex bcd alex lge alex acd 19
('lex', '9')
{}
'''
# 有两个分组定义了key
# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
# ?P<>定义组里匹配内容的key(键),<>里面写key名称,值就是匹配到的内容
r = re.search("a(?P<n1>\w+).*(?P<n2>\d)", origin)
print(r.group()) # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来
print(r.groups()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
print(r.groupdict()) # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
'''
alex bcd alex lge alex acd 19
('lex', '9')
{'n1': 'lex', 'n2': '9'}
'''
- split()函数
'''
根据正则匹配分割字符串,返回分割后的一个列表
split(pattern, string, maxsplit=0, flags=0)
pattern: 正则模型
string : 要匹配的字符串
maxsplit:指定分割个数
flags : 匹配模式
按照一个字符将全部字符串进行分割
'''
import re
origin = "hello alex bcd alex lge alex acd 19"
r = re.split("a", origin) # 根据正则匹配分割字符串
print(r)
'''
['hello ', 'lex bcd ', 'lex lge ', 'lex ', 'cd 19']
'''
# 将匹配到的字符串作为分割标准进行分割
import re
origin = "hello alex bcd alex lge alex 2acd 19"
r = re.split("a\w+", origin) # 根据正则匹配分割字符串
print(r)
'''
['hello ', ' bcd ', ' lge ', ' 2', ' 19']
'''
7. sub()函数
'''
替换匹配成功的指定位置字符串
sub(pattern, repl, string, count=0, flags=0)
pattern: 正则模型
repl : 要替换的字符串
string : 要匹配的字符串
count : 指定匹配个数
flags : 匹配模式
'''
import re
origin = "hello alex bcd alex lge alex acd 19"
r = re.sub("a", "替换", origin) # 替换匹配成功的指定位置字符串
print(r)
'''
hello 替换lex bcd 替换lex lge 替换lex 替换cd 19
'''
8. subn()函数
'''
替换匹配成功的指定位置字符串,并且返回替换次数,可以用两个变量分别接受
subn(pattern, repl, string, count=0, flags=0)
pattern: 正则模型
repl : 要替换的字符串
string : 要匹配的字符串
count : 指定匹配个数
flags : 匹配模式
'''
import re
origin = "hello alex bcd alex lge alex acd 19"
a, b = re.subn("a", "替换", origin) # 替换匹配成功的指定位置字符串,并且返回替换次数,可以用两个变量分别接受
print(a)
print(b)
'''
hello 替换lex bcd 替换lex lge 替换lex 替换cd 19
4
'''
注意事项(掌握)
- r原生字符:让在python里有特殊意义的字符如\b,转换成原生字符(就是去除它在python的特殊意义),不然会给正则表达式有冲突,为了避免这种冲突可以在规则前加原始字符r
- 正则表达式,返回类型为表达式对象的,如:<_sre.SRE_Match object; span=(6, 7), match='a'>,返回对象时,需要用正则方法取字符串,方法有:
- group() # 获取匹配到的所有结果,不管有没有分组将匹配到的全部拿出来,有参取匹配到的第几个如2
- groups() # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分的结果
- groupdict() # 获取模型中匹配到的分组结果,只拿出匹配到的字符串中分组部分定义了key的组结果
- 匹配到的字符串里出现空字符:注意:正则匹配到空字符的情况,如果规则里只有一个组,而组后面是*就表示组里的内容可以是0个或者多过,这样组里就有了两个意思,一个意思是匹配组里的内容,二个意思是匹配组里0内容(即是空白)所以尽量避免用*否则会有可能匹配出空字符串
- ()分组:注意:分组的意义,就是在匹配成功的字符串中,再提取()里的内容,也就是组里面的字符串
- ?:在有分组的情况下findall()函数,不只拿分组里的字符串,拿所有匹配到的字符串,注意?:只用于不是返回正则对象的函数如findall()