一、正则表示达的作用
正则表达式的主要作用是被用来进行文本的检索、替换或者是从一个串中提取出符合我们指定条件的子串,它描述了一种字符串匹配的模式 pattern
二、 正则表示的应用场景:验证 查找 替换
- 验证:比如在网站中进行表单提交时,进行用户名及密码的验证
- 查找:从给定的文本信息中进行快速高效地查找与分析字符串
- 替换:将我们指定格式的文本进行查找,然后将指定的内容进行替换
正则表达式在线测试工具
https://tool.oschina.net/regex
官方文档
https://docs.python.org/zh-cn/3/library/re.html
三、 字符类
.
匹配任意一个字符 ab.可以匹配abc或者abd
[ ]
匹配括号中的任意1个字符 [abcd]可以匹配a b c d
-
在[ ]内表示的字符范围内进行匹配 [0-9a-fA-F]可以匹配任意一个16进制的数字
^
位于[ ]括号内的开头,匹配除括号中的字符之外的任意1个字符 [^xy]匹配xy之外的任意一个字符,比如[^xy]1可以匹配A1、B1但是不能匹配x1、y1
四、 数量限定符
image.png五、 位置相关
image.png六、 特殊符号
image.png七、 正则修饰符
image.png八、 re模块常用方法
image.png九、方法演练
1.re01_查找的相关方法
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/1 18:27
# @File : re01_查找的相关方法.py
# @Author: adeng
# @Date : 2020/11/1
============================
"""
import re
from collections.abc import Iterable
"""
找相关的方法
1.match和 search:
同点:1.只对字符串查询一次2.返回值类型都是re. Match类型的对象
不同点: match是从头开始匹配,一旦匹配失败,就返回one; search是在整个字符串里匹配
2.finditer:查到所有的匹配数据,放在一个可迭代对象里
3.findall: 查到所有数据,放在一个列表里.返回列表
4.fullmatch: 完整匹配,字符串需要完全满足正则规则。返回一个re.Match对象
"""
m1 = re.match(r"good", r"hello good 123 good")
print(m1)
m2 = re.match(r"good", r"good 123 good")
print(m2)
m3 = re.search(r"good", r"hello good 123 good")
print(m2)
# 结果:
# None match从开头匹配,匹配不到返回None,只能匹配一次
# <re.Match object; span=(0, 4), match='good'> (0, 4)可以成索引0--索引3 取头不取尾
# <re.Match object; span=(0, 4), match='good'>
#---------finditer---------
# finditer 返回的结果是一个迭代对象
# 可迭代对象里的数据是匹配到的所有结果,是一个re.Match对象
m4 = re.finditer(r"x", "bxcxdx1x3x")
if isinstance(m4, Iterable):
print(f'{m4}是可迭代对象')
for i in m4:
print(i)
print(i.group())
# --------------findall-------------
m5 = re.findall(r"x1", "bxcxdx1x3x")
print(m5) # ['x', 'x', 'x', 'x', 'x']
#----------fullmatch---------
m6 = re.fullmatch(r"hello", r"hello word")
print(m6) # 返回为None,因为fullmatch是完整匹配
m7 = re.fullmatch(r"hello word", r"hello word")
print(m7)
#---------- fullmatch 完整匹配--------------
m8 = re.fullmatch(r"h.*d", r"hello word")
print(m8)
2.re02_re.Match类的介绍
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/2 17:12
# @File : re02_re.Match类的介绍.py
# @Author: adeng
# @Date : 2020/11/2
============================
"""
import re
m1 = re.search(r"xp", r"11xp33")
print(m1)
# dir()内置方法可以查看对象有什么方法
print(dir(m1))
# 需要掌握span() group()
print(m1.pos, m1.endpos) # pos 开始索引 endpos结束索引 取头不取尾
print(m1.span()) # (2, 4) # 开始下标 和结束下标 取头不取尾 类似切片
# 使用group()匹配字符串的结果
print(m1.group()) # xp
# group方法表示正则表达式的分组
#1.在正则表达式里使用()表示一个分组
#2.如果没有分组,默认只有一组
#3.分组的下标从0开始
#正则表达式有四个分组
m2 = re.search(r"(a9.*)(8.*)(3.*)", r"a91a,8o,3pp")
print(m2.group()) # "a91a,8o,3pp" 匹配所有,把整个正则表达式当着一个整体
print(m2.group(0)) # 第0组, 同group()
print(m2.group(1)) # a91a, 第2组
print(m2.group(2)) # 8o, 第3组
print(m2.group(3)) # 3pp 第4组
# print(m2.group(4)) #报错 没有第5组
print(m2.groups()) # 匹配结果是一个元组 ('a91a,', '8o,', '3pp')
# groupdict 获取到分组 组成的字典
print(m2.groupdict()) # 这里返回结果是一个{}
# (?P<name> 表达式) 可以给分组取 一个名字
m3 = re.search(r"(?P<name>a9.*)(?P<key1>8.*)(3.*)", r"a91a,8o,3pp")
print(m3.groupdict()) # {'name': 'a91a,', 'key1': '8o,'}
# 可以通过group(名字) 来取值
print(m3.group("name")) # a91a,
# 既然是一个字典就可以通过key拿到 value
print(m3.groupdict()["key1"]) # 8o,
#-----可以通过分组名和分组的下标获取 匹配的值---
print(m3.group("name")) # a91a,
print(m3.group(1)) # a91a,
3.re03_re.compile方法的使用
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/2 23:45
# @File : re03_re.compile方法的使用.py
# @Author: adeng
# @Date : 2020/11/2
============================
"""
import re
# 在re模块里,可以使用re.方法调用函数,还可以调用re.compile得到一个对象
m = re.search(r"m.*f", r"24mfdafoo")
print(m.group())
# 生成一个匹配规则
r = re.compile(r"m.*f")
m1= r.search("24mfdafoo")
print(m1.group())
4.re04_正则修饰符
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/2 23:51
# @File : re04_正则修饰符.py
# @Author: adeng
# @Date : 2020/11/2
============================
"""
import re
"""
re.I 忽略大小写(常用)
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,能匹配到换行\n,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予更灵活的格式,以便将正则表达式写得更易于理解。
"""
# . 匹配任意一个字符除\n换行符
m = re.search(r"m.*5", "324mfafae\n54321432", flags=re.S)
print(m) # <re.Match object; span=(3, 11), match='mfafae\n5'>
n = re.search(r"Xa", "xA1", re.I)
print(n)
#------re.M 能匹配到换行---
y = re.findall(r"\w+$", "I am rdj\n hello word\n, this is app")
print(y) # ['app']
# flag = re.M 加上看看,匹配以数字字母下划线至少1个 结尾的
y = re.findall(r"\w+$", "I am rdj\n hello word\n, this is app", re.M)
print(y) # ['rdj', 'word', 'app']
5.re05_正则表达式规则
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 0:10
# @File : re05_正则表达式规则.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
# 1. 数字和字母表示本身
# 2. 字母前加\ 有特殊含义
# 3. 绝大多数标点符号有特殊含义
# 4. 如果要使用标点符号 要用\ 转义
r = re.search("x1", "dafax1fdas")
print(r)
print(re.search("\+", r"5+3"))
# 手机号正则表达式
phone = r'^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$'
card_id = "^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$"
6.re06_标点符号的特殊含义
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 9:59
# @File : re06_标点符号的特殊含义.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
# 1. () 分组 将表达式的一部分括起来,可以对整个单元使用数量限定符,匹配括号中的内容
m = re.search("(b.*d)", "12b3243d2!!d3432")
print(m.group(1)) # b3243d2!!d
#2. . 匹配任意字符,除了\n.如果要匹配到所有传参flag=re.S
m1 = re.search("\d+.*?","fdasjflkj44jjj!!")
print(m1) # 加了?非贪婪只匹配到44,.任意字符取的0个,所以44后面的都没匹配到
m1 = re.search("\d+.+?","fdasjflkj44jjj!!")
print(m1) # 加了?非贪婪只匹配到44j,.任意字符只取了1个,所以后面的都没匹配到
#3. [] 匹配区间的任意1个字符,只能取1个,一般配合-,-表示区间如[3-8]表示3到8任意1个
m2 =re.search("[43,1-9]*", "5431199034")
print(m2) # 5431199
m2 =re.search("[0-5a-zA-Z]*", "54dfsaf566JKLJL")
print(m2) # 54dfsaf5
#4. | 用来表示或者 和[]有一定相似,但是也有区别
# [] 里的值表示的是区间, | 就是可选值
m3 = re.search("f(ac|ze|c)","1fze12fcc")
print(m3) # fze
#5. {} 用来限定出现的次数
# {N} 匹配前面紧跟字符精确到N次 [1-9][0-9]{2},匹配100到999的整数,{2}表示[0-9]匹配两个数字
# {N,} 匹配前面紧跟字符最少N次
# {N,M} 匹配前面紧跟字符的至少N次,最多M次 [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3},匹配IP地址,其中.号是特殊字符,需要使用转义字符\
m4 = re.search("3{2}","a11333")
print(m4) # 33
m4 = re.search("3{1,}","a11333333")
print(m4) # 333333
m4 = re.search("113{,2}","a11333333a")
print(m4) # 1133
m4 = re.search("3{1,4}","a11333333")
print(m4) # 3333
# 6. * 表示0次以上 等价于{0,}
m5 = re.search("1x*1", "11xxx132")
print(m5.group()) # 11 这里注意一个坑,因为search方法只匹配一次,X取0次就会匹配到11
m5 = re.search("11x*1", "11xxx132")
print(m5) # 11xxx1 这样就能匹配到多个XXX
# 7. + 1个以上
m6 = re.search("1x+1", "11xxx132")
print(m6) # 1xxx1
#8. ? 0次或1次 还有一个用法是贪婪和非贪婪
m7 = re.search("go?d", "god")
print(m7) # god
#9. ^以指定XX开头, $以XX结尾
m8 = re.search("^open.*888$","open4654erawraw \.888")
print(m8) # 'open4654erawraw \\.888'
7.re07_字母的特殊函数
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 11:11
# @File : re07_字母的特殊函数.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
# 字母表示本身,前面加\ 会有特殊含义
# \n: 换行 \t:制表符 \s:空白符 \S:非空白字符
#\d:数字 等价于[0-9] \D:表示非数字 等价于 [^0-9],^放在[]里面表示非,放在外面就是从开头匹配哦
import re
print(re.search(r"x\d*p", "12x343p")) # x343p
print(re.search(r"\D+", "he110")) # he
# \w:数字字母 _,等价于[0-9a-zA-Z_] ,就是非标点符号
print(re.findall("\w+", "h+E-0.hx_0.pl")) # ['h', 'E', '0', 'hx_0', 'pl']
print(re.findall("\w+", "我-爱.你,")) # ['我', '爱', '你'] 中文\w也能拿
print(re.findall("\W+", "h+E-0.hx_0.pl")) # ['+', '-', '.', '.']
8. re08_正则表达式练习
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 11:48
# @File : re08_正则表达式练习.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
#判断用户输入的内容是否是数字,如果是数字转换成为数字类型
num = input("请输入一段数字:")
# \d+\.?\d+ 输入3有一个BUG,()?括号里作为整体出现0次或者1次,所以修改成 \d+(\.?\d+)?
r =re.compile("\d+(\.?\d+)?")
n = r.fullmatch(num) #
if n:
print(float(num))
else:
print("输入的不是一个数字")
# 1.用户名匹配由数字、大小写字母、下划线和中横线-组成,长度为4到14位,并且不能以数字开头。
# ^\D[\w\-]{3,13}
r = re.match(r"^\D[\w\-]{3,13}", "rendj1212...")
print(r.group())
#2. email地址
# [\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
# 手机号
phone = r'^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[05-9]))\d{8}$'
# 身份证
card_id = "^([1-9]\d{5})((18|19|20)\d{2})((0[1-9])|(1[0-2]))(([0-2][1-9])|([10|20|30|31]))\d{3}[0-9Xx]$"
9.re09_正则替换
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 13:58
# @File : re09_正则替换.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
s = "1fdsafa32gdfs4g"
r = re.sub(r"\d", "我", s)
print(r) # 我fdsafa我我gdfs我g
# 去除标点符号
print(re.sub("[^\w]", "", "fafa.\]\+! \-")) # fafa
# sub第一个参数为函数名
def add(x):
y = int(x.group())
y = y +2
return str(y)
r = re.sub(r"\d+", add, "fafa40,fda50,pp")
print(r) # fafa42,fda52,pp
# 将空格替换成,
print(re.sub(r"\s+", ",", "I am adeng")) # I,am,adeng
10.re10_贪婪模式和非贪婪模式
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 14:18
# @File : re10_贪婪模式和非贪婪模式.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
m = re.search(r"p.*1", "312pfdsa1fa1")
print(m) #pfdsa1fa1
# .*? 尽可能少的匹配 任意字符
m = re.search(r"p.+?a", "312pfdsa1fa1111")
print(m) # pfdsa
x = re.match(r"aa(\d{2,})", "aa2343ddd")
print(x.group(0)) # aa2343
print(x.group(1)) # 2343
x1 = re.match(r"aa(\d{2,}?)", "aa2343ddd")
print(x1.group(0)) # aa23
print(x1.group(1)) # 23
x2 = re.match("aa(\d+)ddd", "aa2343ddd")
print(x2.group()) # aa2343ddd
print(x2.group(1)) # 2343
# \d+? 尽可能的少匹配,这里有点特殊,当匹配一个数字,后面匹配不到这时候就能怎么匹配到就怎么匹配
x3 = re.match(r"aa(\d+?)ddd", "aa2343ddd")
print(x3.group(0)) # aa2343ddd
print(x3.group(1)) # 2343
# 这个案例和上面那个有点区别
x4 = re.match(r"aa(\d+?).*", "aa2343ddd")
print(x4.group(0)) # aa2343ddd
print(x4.group(1)) # 2 .*这时候匹配的是343ddd
x5 = re.match(r"aa(\d??)(.*)", "aa2343ddd")
print(x5.group(0)) # aa2343ddd
print(x5.group(1)) # 空
print(x5.group(1)) # 2 .*这时候匹配的是2343ddd
11.re11_正则练习题
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/11/3 16:54
# @File : re11_正则练习题.py
# @Author: adeng
# @Date : 2020/11/3
============================
"""
import re
# 1.用户名匹配由数字、大小写字母、下划线和中横线-组成,长度为4到14位,并且不能以数字开头。
# ^\D[\w\-]{3,13}
# \w 能匹配到中文
# r = re.match(r"^[a-zA-Z_][\w\-]{3,13}", "rendj的12*1")
r = re.match(r"^[a-zA-Z_][0-9a-zA-Z_\-]{3,13}", "rendj12*1")
if r is not None:
print(r.group())
#密码匹配
#1.不能包含!@%^&*字符2.必须以字母开头3.长度在6到12位
r = re.fullmatch(r"[a-zA-Z][^!@%^&*]{5,11}", "rendw*w1ww")
if r is not None:
print(r.group())
else:
print("密码不符合规范")
#练习题 demo.txt 内容太如下
"""
1000phone hello python
mobiletrain 大数据
1000phone java
mobiletrain html5
mobiletrain 云计算
查找文件中以1000phone开头的语句,并且保存到列表中。
"""
with open(r"demo.txt", "r") as f:
data = f.read()
pass
print(data)
r = re.findall(r"1000phone.*", data) #.* 点遇到\n就不找了,接着从剩下的继续查找
if r :
print(r)
# 练习题ipv4 格式的IP 地址匹配
# 提示 IP地址的范围是0.0.0.0-255.255.255.255
# compile1 = "(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\."
# outs = input("输入:")
# r = re.fullmatch(compile1*3+compile1[:-2], outs)
# if r :
# print(r.group())
#
# else:
# print("IP地址不合法")
# 练习题
# 练习题
# 提取用户输入数据中的数值(数值包括正负数 还包括证书和小数在内)并求和
# 例如:"-3.14goob87nice19bye" -----> -3.14+87+19 = 102.86
"""
- 可能有可能没有: -?
113.14
0.14 小数点前可能是0,可能是1-9:0|[1-9]\d*
小数点可能有 可能没有 看成一个整体可能0个 可能1个 (\.\d+)?
"""
# nums = input("输入:")
x = re.finditer(r"-?(0|[1-9]\d*)(\.\d*)?", "-3.14goob87nice19bye") #(\.\d*)?看着一个整体可能有 可能没有
print(x)
for i in x:
print(i)
12.re12_正则分组
():分组 ?:可以让结果为匹配的全部内容
findall 分组返回的是 引号内正则表达式匹配的字符串中()中的内容
findall分组有多个括号 返回的是以元组为元素的列表。如下演示
import re
# ():分组 ?:可以让结果为匹配的全部内容
print(re.findall('ab+', 'ababab123')) # ['ab', 'ab', 'ab']
# findall ()分组。返回的是 引号内正则表达式匹配的字符串中()中的内容
print(re.findall('(ab)+123', 'ababab123')) # ['ab'],匹配到末尾的ab123中的ab
print(re.findall('(?:ab)+123', 'ababab123')) # findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
print(re.findall('href="(.*?)"', '<a href="http://www.baidu.com">点击</a>')) # ['http://www.baidu.com']
print(re.findall('href="(?:.*?)"', '<a href="http://www.baidu.com">点击</a>')) # ['href="http://www.baidu.com"']
# |
print(re.findall('compan(?:y|ies)', 'Too many companies have gone bankrupt, and the next one is my company'))
print(re.findall('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$', 'alex make love')) # [('alex', ' ', 'make', ' ', 'love', '')]
print(re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$', r'\5\2\3\4\1', 'alex make love')) # ===> love make alex
r = re.findall(r"-?\d+\.\d+|-?\d+", "1-2*(60+(-40.35/5)-(-4*3))")
print(r) # ['1', '-2', '60', '-40.35', '5', '-4', '3']
m = re.findall("ds(.*)(\d+)p{3}(\d+)[a-z]*", "dsfa123ppp4231one")
print(m) # [('fa12', '3', '4231')]
c = re.findall("z|fo*", "z\nzood\nfood")
print(c) # ['z', 'z', 'foo']
c1 = re.findall("[zf]o*", "z\nzood\nfood")
print(c1) # ['z', 'zoo', 'foo']
# 返回的是 引号内正则表达式匹配的字符串中()中的内容
c2 = re.findall("[zf](o*)", "z\nzood\nfood")
print(c2) # ["", "oo", "oo"]
print(re.findall("[zf]o*d*", "z\nzood\nfood")) # ['z', 'zood', 'food']
c3 = re.findall("[zf](o*)(d*)", "z\nzood\nfood")
print(c3) # [('', ''), ('oo', 'd'), ('oo', 'd')]
5、re的匹配语法1实例:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
import re
# 正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re
s = 'abc123d45'
# re.match(pattern, string, flags=0) 从头开始匹配,只匹配第一个
'''
pattern 正则表达式 pattern 正则表达式 flags 标志位,用于控制正则表达式的匹配方式
'''
print(re.match('[0-9]',s)) # 因为第一个是’a‘所以没有匹配到
print(re.match('[0-9]','15abc234')) # <_sre.SRE_Match object; span=(0, 1), match='1'>
# re.search() 遇到符合要求的就返回,不再继续向后找
print(re.search('[0-9]','ab12c3d')) # <_sre.SRE_Match object; span=(2, 3), match='1'>
# 先判断是否匹配到,是的话 通过re.search().group() 返回匹配到的值
# re.findall() 全局查找,有多少符合返回多少,以列表的形式返回
print(re.findall('[0-9]','a1b2c3d4')) # ['1', '2', '3', '4']
# '.' 默认匹配除\n之外的任意一个字符
print(re.match('.','abc12d')) # <_sre.SRE_Match object; span=(0, 1), match='a'>
print(re.match('..','abc12d')) # <_sre.SRE_Match object; span=(0, 2), match='ab'>
print(re.search('.','ab12cd')) # <_sre.SRE_Match object; span=(0, 1), match='a'>
# ' ^ ' 匹配字符开头
print(re.match('^a','ab12cd')) # <_sre.SRE_Match object; span=(0, 1), match='a'>
print(re.match('^ab','ab12cd')) # <_sre.SRE_Match object; span=(0, 2), match='ab'>
print(re.search('^ab','ab12cd')) # <_sre.SRE_Match object; span=(0, 2), match='ab'>
# '$' 匹配字符结尾
print(re.match('d$','ab12cd'))# 无法获取
print(re.search('d$','ab12cd')) # <_sre.SRE_Match object; span=(5, 6), match='d'>
print(re.search('cd$','ab1cd2cd')) # <_sre.SRE_Match object; span=(6, 8), match='cd'>
# '*' 匹配*号前的字符0次或多次
print(re.match('d*','ad123dd')) # 没有匹配到
print(re.search('ab*','a123abv').group()) # a
print(re.search('a*','aaaabac').group()) # aaaa
# '+' 匹配前一个字符1次或多次
print(re.findall("ab+","ab+cd+abb+bba") ) # ['ab', 'abb']
print(re.findall('ab+','aabadfbab')) # ['ab', 'ab']
# '?' 匹配前一个字符1次或0次
print(re.search('a?','alaex').group()) # a
# '{m}'匹配前一个字符m次
print(re.search('b{3}','alexbbbs').group()) # 匹配到'bbb'
# '{n,m}' 匹配前一个字符n到m次
print(re.findall("ab{1,3}","abb abc abbcbbb")) # ['abb', 'ab', 'abb']
# '|' 匹配|左或|右的字符
print(re.search("abc|ABC","ABCBabcCD").group()) # ABC
# (...)' 分组匹配
print( re.search("(abc){2}a(123|45)", "abcabca456c").group()) # abcabca45
print(re.search('[q-z]{1,3}','ab123qwe').group()) # qw
print(re.search('([a-z]+)([0-9]+)','zbc12a5').groups()) # ('zbc', '12')
re的匹配语法2实例:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
import re
# '\A' 只从字符开头匹配
print(re.search("\Aabc","alexabc")) # 匹配不到的,相当于re.match('abc',"alexabc") 或^
print(re.search('\Aale','alexabc').group()) # ale
# '\Z' 匹配字符结尾,同$
print(re.search('abc\Z','alexabc').group()) # abc
# '\d' 匹配数字0-9
print(re.search('\d+','123ab4').group()) # 123
# '\D' 匹配非数字
print(re.search('\D+','asd$12!@').group()) # asd$
print(re.findall('\D+','asd$12!@')) # ['asd$', '!@']
# '\w' 匹配[A-Za-z0-9]
print(re.search('\w+','123abA!4').group()) # 123abA
# '\W' 匹配 非 [A-Za-z0-9]
print(re.search('\W+','123abA!4').group()) # !
# '\s' 匹配空白字符、\t、\n、\r 结果 '\t'
print(re.search("\s+","ab\tc1\n3")) # <_sre.SRE_Match object; span=(2, 3), match='\t'>
# '(?P<name>...)' 分组匹配 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
s = '412142199612012510'
res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',s).groups()
print(res) # ('412', '142', '1996')
# re.split 以匹配到的字符当做列表分隔符
s = 'qeqwe135asdf14as!df-312qw'
print(re.split('\d+|!|-',s)) # ['qeqwe', 'asdf', 'as', 'df', '', 'qw']
cunt ='12334+2312*12-56/8%2'
print(re.split('[\+\*-/%]',cunt,maxsplit=3)) # ['12334', '2312', '12', '56/8%2']
# re.fullmatch 全部匹配
print(re.fullmatch('\w+@\w+\.(com|cn|edu)','ccqwe@asdf.com').group()) # ccqwe@asdf.com
# re.compile 先制定规则,再匹配,提高效率
str = re.compile('\d+@\w+\.com')
print(str.fullmatch('935259249@qq.com').group()) # 935259249@qq.com
# re.sub 替换
s = 'qwert1234zx666hyt999'
print(re.sub('\d+','*',s)) # qwert*zx*hyt*
print(re.sub('\d+','%',s,count=2)) # qwert%zx%hyt999
'''
Flags标志符
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为
S(DOTALL): 改变'.'的行为,make the '.' special character match any character at all, including a newline; without this flag, '.' will match anything except a newline.
X(re.VERBOSE) 可以给你的表达式写注释,使其更可读,下面这2个意思一样
'''
# re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
print(re.search('a','Alehello',re.I).group()) # A
# X(re.VERBOSE) 可以给你的表达式写注释,使其更可读,下面这2个意思一样
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""",
re.X)
b = re.compile(r"\d+\.\d*")
# =================================匹配模式=================================
#一对一的匹配
# 'hello'.replace(old,new)
# 'hello'.find('pattern')
#正则匹配
import re
#\w与\W
print(re.findall('\w','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
print(re.findall('\W','hello egon 123')) #[' ', ' ']
#\s与\S
print(re.findall('\s','hello egon 123')) #[' ', ' ', ' ', ' ']
print(re.findall('\S','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
#\n \t都是空,都可以被\s匹配
print(re.findall('\s','hello \n egon \t 123')) #[' ', '\n', ' ', ' ', '\t', ' ']
#\n与\t
print(re.findall(r'\n','hello egon \n123')) #['\n']
print(re.findall(r'\t','hello egon\t123')) #['\n']
#\d与\D
print(re.findall('\d','hello egon 123')) #['1', '2', '3']
print(re.findall('\D','hello egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', 'e', 'g', 'o', 'n', ' ']
#\A与\Z
print(re.findall('\Ahe','hello egon 123')) #['he'],\A==>^
print(re.findall('123\Z','hello egon 123')) #['he'],\Z==>$
#^与$
print(re.findall('^h','hello egon 123')) #['h']
print(re.findall('3$','hello egon 123')) #['3']
# 重复匹配:| . | * | ? | .* | .*? | + | {n,m} |
#.
print(re.findall('a.b','a1b')) #['a1b']
print(re.findall('a.b','a1b a*b a b aaab')) #['a1b', 'a*b', 'a b', 'aab']
print(re.findall('a.b','a\nb')) #[]
print(re.findall('a.b','a\nb',re.S)) #['a\nb']
print(re.findall('a.b','a\nb',re.DOTALL)) #['a\nb']同上一条意思一样
#*
print(re.findall('ab*','bbbbbbb')) #[]
print(re.findall('ab*','a')) #['a']
print(re.findall('ab*','abbbb')) #['abbbb']
#?
print(re.findall('ab?','a')) #['a']
print(re.findall('ab?','abbb')) #['ab']
#匹配所有包含小数在内的数字
print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']
#.*默认为贪婪匹配
print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']
#.*?为非贪婪匹配:推荐使用
print(re.findall('a.*?b','a1b22222222b')) #['a1b']
#+
print(re.findall('ab+','a')) #[]
print(re.findall('ab+','abbb')) #['abbb']
#{n,m}
print(re.findall('ab{2}','abbb')) #['abb']
print(re.findall('ab{2,4}','abbb')) #['abb']
print(re.findall('ab{1,}','abbb')) #'ab{1,}' ===> 'ab+'
print(re.findall('ab{0,}','abbb')) #'ab{0,}' ===> 'ab*'
#[]
print(re.findall('a[1*-]b','a1b a*b a-b')) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾
print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]内的^代表的意思是取反,所以结果为['a=b']
print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]内的^代表的意思是取反,所以结果为['a=b']
#\# print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
print(re.findall(r'a\\c','a\c')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义
print(re.findall('a\\\\c','a\c')) #同上面的意思一样,和上面的结果一样都是['a\\c']
#():分组
print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']
print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab
print(re.findall('(?:ab)+123','ababab123')) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>'))#['http://www.baidu.com']
print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">点击</a>'))#['href="http://www.baidu.com"']
#|
print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))
# ===========================re模块提供的方法介绍===========================
import re
#1
print(re.findall('e','alex make love') ) #['e', 'e', 'e'],返回所有满足匹配条件的结果,放在列表里
#2
print(re.search('e','alex make love').group()) #e,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
#3
print(re.match('e','alex make love')) #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match
#4
print(re.split('[ab]','abcd')) #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割
#5
print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默认替换所有
print('===>',re.sub('a','A','alex make love',1)) #===> Alex make love
print('===>',re.sub('a','A','alex make love',2)) #===> Alex mAke love
print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','alex make love')) #===> love make alex
print('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),结果带有总共替换的个数
#6
obj=re.compile('\d{2}')
print(obj.search('abc123eeee').group()) #12
print(obj.findall('abc123eeee')) #['12'],重用了obj
#补充二
import re#使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所有即使匹配成功小数也不会存入结果#而不是小数时,就去匹配(-?\d+),匹配到的自然就是,非小数的数,在此处即整数#print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整数['1', '-2', '60', '', '5', '-4', '3']#找到所有数字:print(re.findall('\D?(\-?\d+\.?\d*)',"1-2*(60+(-40.35/5)-(-4*3))")) # ['1','2','60','-40.35','5','-4','3']
#计算器作业参考:http://www.cnblogs.com/wupeiqi/articles/4949995.html
expression='1-2*((60+2*(-3-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
content=re.search('\(([\-\+\*\/]*\d+\.?\d*)+\)',expression).group() #(-3-40.0/5)
findall 和search的区别
import re
#为何同样的表达式search与findall却有不同结果:
print(re.search('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))").group()) #(-40.35/5)
print(re.findall('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))")) #['/5', '*3']
#看这个例子:(\d)+相当于(\d)(\d)(\d)(\d)...,是一系列分组
print(re.search('(\d)+','123').group()) #group的作用是将所有组拼接到一起显示出来 123
print(re.findall('(\d)+','123')) #findall结果是组内的结果,且是最后一个组的结果 ["3"]
print(re.findall('(?:\d)+','123')) #findall结果是组内的结果,且是最后一个组的结果 ?:可以让结果为匹配的全部内容 ["123"]
sub方法 \数字 取第几个括号的内容
# 用\1取得第一个括号的内容
# 用法:将123与456换位置
import re
content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
# content=re.sub('(Extra.*?)(\d+)(\s)(\d+)(.*?strings)',r'\1\4\3\2\5',content)
c=re.search('(\d+)(\s)(\d+)',content)
print(c.group(1,2,3))
content=re.sub('(\d+)(\s)(\d+)',r'\3\2\1',content)
print(content)
"""
('123', ' ', '456')
Extra strings Hello 456 123 World_This is a Regex Demo Extra strings
"""
#在线调试工具:tool.oschina.net/regex/#
import re
s='''
http://www.baidu.com
010-3141
'''
#最常规匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('Hello\s\d\d\d\s\d{3}\s\w{10}.*Demo',content)
# print(res)
# print(res.group())
# print(res.span())
#泛匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello.*Demo',content)
# print(res.group())
#匹配目标,获得指定数据
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello\s(\d+)\s(\d+)\s.*Demo',content)
# print(res.group()) #取所有匹配的内容
# print(res.group(1)) #取匹配的第一个括号内的内容
# print(res.group(2)) #去陪陪的第二个括号内的内容
#贪婪匹配:.*代表匹配尽可能多的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字
#非贪婪匹配:?匹配尽可能少的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*?(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字
#匹配模式:.不能匹配换行符
content='''Hello 123456 World_This
is a Regex Demo
'''
# res=re.match('He.*?(\d+).*?Demo$',content)
# print(res) #输出None
# res=re.match('He.*?(\d+).*?Demo$',content,re.S) #re.S让.可以匹配换行符
# print(res)
# print(res.group(1))
#转义:\
# content='price is $5.00'
# res=re.match('price is $5.00',content)
# print(res)
#
# res=re.match('price is \$5\.00',content)
# print(res)
#总结:尽量精简,详细的如下
# 尽量使用泛匹配模式.*
# 尽量使用非贪婪模式:.*?
# 使用括号得到匹配目标:用group(n)去取得结果
# 有换行符就用re.S:修改模式
#re.search:会扫描整个字符串,不会从头开始,找到第一个匹配的结果就会返回
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.match('Hello.*?(\d+).*?Demo',content)
# print(res) #输出结果为None
#
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.search('Hello.*?(\d+).*?Demo',content) #
# print(res.group(1)) #输出结果为
#re.search:只要一个结果,匹配演练,
import re
content='''
<tbody>
<tr id="4766303201494371851675" class="even "><td><div class="hd"><span class="num">1</span><div class="rk "><span class="u-icn u-icn-75"></span></div></div></td><td class="rank"><div class="f-cb"><div class="tt"><a href="/song?id=476630320"><img class="rpic" src="http://p1.music.126.net/Wl7T1LBRhZFg0O26nnR2iQ==/19217264230385030.jpg?param=50y50&quality=100"></a><span data-res-id="476630320" "
# res=re.search('<a\shref=.*?<b\stitle="(.*?)".*?b>',content)
# print(res.group(1))
#re.findall:找到符合条件的所有结果
# res=re.findall('<a\shref=.*?<b\stitle="(.*?)".*?b>',content)
# for i in res:
# print(i)
#re.sub:字符串替换
import re
content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
# content=re.sub('\d+','',content)
# print(content)
#用\1取得第一个括号的内容
#用法:将123与456换位置
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# # content=re.sub('(Extra.*?)(\d+)(\s)(\d+)(.*?strings)',r'\1\4\3\2\5',content)
# content=re.sub('(\d+)(\s)(\d+)',r'\3\2\1',content)
# print(content)
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.search('Extra.*?(\d+).*strings',content)
# print(res.group(1))
# import requests,re
# respone=requests.get('https://book.douban.com/').text
# print(respone)
# print('======'*1000)
# print('======'*1000)
# print('======'*1000)
# print('======'*1000)
# res=re.findall('<li.*?cover.*?href="(.*?)".*?title="(.*?)">.*?more-meta.*?author">(.*?)</span.*?year">(.*?)</span.*?publisher">(.*?)</span.*?</li>',respone,re.S)
# # res=re.findall('<li.*?cover.*?href="(.*?)".*?more-meta.*?author">(.*?)</span.*?year">(.*?)</span.*?publisher">(.*?)</span>.*?</li>',respone,re.S)
#
#
# for i in res:
# print('%s %s %s %s' %(i[0].strip(),i[1].strip(),i[2].strip(),i[3].strip()))
作业
import re
# 1、匹配密码,密码必须是由6位数字与字母组成,并且不能是纯数字也不能是纯字母
# 1.1 知识点:# ?!pattern,表示在没有配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
# 1.2 答案:
print(re.search("(?!^[0-9]+$)(?!^[a-zA-Z]+$)^[0-9A-Za-z]{6}$","123asf").group()) # 123asf
# 1.3 解释:
# 上述正则的意思为:在匹配(?!^[0-9]+$)以及(?!^[a-zA-Z]+$)过后,如果字符串成功后在从头去匹配(?!^[a-zA-Z]+$),最终匹配完。
# 2、匹配密码,密码强度:强,必须包含大写,小写和数字,和特殊字符(!,@,#,%,&),且大于6位
# 2.1 知识点:# ?=pattern,表示在配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
# 2.2 答案:
# while True:
# pwd = input("please your password: ").strip() # 比如输入:Aa3@adf123
# pwd_pattern= re.compile("(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#%&])^([a-zA-Z0-9!@#%&]){6,}$")
# if pwd_pattern.search(pwd) is None:
# print("密码强度不够")
# else:
# break
# 2.3 解释:
# 上述正则表达式的意思:
#(1)首先是(?=.*[A-Z])匹配,.*表示密码中可以包含多个字符,[A-Z]代表密码中需要包含至少一个大写字母,注意一定不要去掉.*写成(?=[A-Z]),那样表示密码只能由一个字符组成,该字符是大写字母
#(2)其次是(?=.*[a-z])匹配,同上,确保密码中必须至少有一个小写字母
#(3)然后是(?=.*[0-9])匹配,同上,确保密码中必须至少有一个数字
#(4)然后是(?=.*[!@#%&])匹配,同上,,确保密码中必须至少有一个特殊符号!@#%&
#(5)最后是^([a-zA-Z0-9!@#%&]){6,}$,确保密码是由[a-zA-Z0-9!@#%&]字符构成,至少有6位
# 3、匹配email
# print(re.findall("(?:[a-zA-Z0-9]+)@(?:[0-9a-zA-Z]+).com","18611323113@163.com xxx@qq.com"))
# 4、匹配身份证
# your_id=input(">>: ").strip()
# print(re.findall("^([0-9]){17}([0-9]|X)$",your_id)) # 17个数字组成,最后一个字符可以是数字或X
# 5、匹配用户名,包含字母或者数字,且8位
# print(re.findall("^[0-9a-zA-Z]{8}$","egonlinh"))
# 5.1、要求输入的内容只能是汉字
# name=input('>>: ').strip()
# print(re.search(r'[\u4E00-\u9fa5]+',name))
# 6、取出字符串里的数字
# print(re.findall(r'\d+(?:\.\d+)?', 'sww123kw11.333e2lkd'))
# 7、取出所有负整数
# print(re.findall(r'-\d+', '-12,3,54,-13.11,64,-9')) # 错误答案
# print(re.findall(r'(?!-\d+\.\d+)-\d+', '-12,3,54,-13.11,64,-9')) # 正确答案
# 8、所有数字
# print(re.findall(r'\-?\d+(?:\.\d+)?', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 9、所有负数
# print(re.findall(r'\-\d+(?:\.\d+)?', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 10、所有的非负浮点数
print(re.findall(r'\d+\.\d+', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 11、
msg = """
中文名 贝拉克·侯赛因·奥巴马
外文名 Barack Hussein Obama II
别名 欧巴马
性 别 男
国籍 美国
民 族 德裔族
出生地 美国夏威夷州檀香山
出生日期 1961年8月4日
职 业政治家、律师、总统
毕业院校 哥伦比亚大学,哈佛大学
信 仰新教
主要成就 1996年伊利诺伊州参议员
主要成就 美国第56届、57届总统 2009年诺贝尔和平奖获得者 时代周刊年度风云人物2008、2011 任期内清除本·拉登
代表作品 《我相信变革》《我父亲的梦想》《无畏的希望》
所属政党美国民主党
血 型 AB型
学 院西方学院
妻 子 米歇尔·拉沃恩·奥巴马
"""
#外文名
print(re.findall("外文名 (.*)",msg))
#出生日期
print(re.findall('出生日期 (\d{4})年(\d+)月(\d+)日',msg))
#妻子姓名
print(re.findall('妻 子 (\S+)',msg))
网友评论