python笔记更新(正则表达式)

正则表达式

正则表达式的介绍

正则表达式是一个特殊的字符序列,计算机科学的一个概念。通常被用来检索、替换那些符合某个模型(规则)的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。在python中需要通过正则表达式对字符串进行匹配的时候,可以使用re模块。re模块使python语言拥有全部的正则表达式功能。

特点:

  1. 灵活性、逻辑性和功能性非常强
  2. 可以迅速地用极简单的方式达到字符串的复杂控制
  3. 对于刚接触的人来说,比较晦涩难懂
# 1. 查找 2. 替换
import re

x = 'hello\\nworld'
# 在正则表达式里,如果想要匹配一个 \ 需要使用 \\\\
# 第一个参数就是正则匹配规则
# 第二个参数表示需要匹配的字符串
# m = re.search('\\\\', x)
# 还可以在字符串前面加r, \\就表示\
m = re.search(r'\\', x)
# search 和 match 方法的执行结果是一个Match类型的对象
print(m)  # <re.Match object; span=(5, 6), match='\\'>

正则查找相关的方法

# 查找相关的方法
# match 和 search:
# 共同点:1.返回的结果是一个re.Match对象 2.只对字符串查询一次
# 不同点:1.match是从头开始匹配,一旦匹配失败,就返回None;search是在整个字符串里匹配
# finditer:查找到所有的匹配数据,放到一个可迭代对象里
# findall:把查找到的所有的字符串结果放到一个列表里
# fullmatch:完整匹配,字符串需要完全满足正则规则才会有结果,否则就是None
import re
from collections.abc import Iterable

m1 = re.match(r'hello', 'hello world good morning')
print(m1)  # <re.Match object; span=(0, 5), match='hello'>
m2 = re.search(r'hello', 'hello world good morning')
print(m2)  # <re.Match object; span=(0, 5), match='hello'>
m3 = re.match(r'good', 'hello world good morning')
print(m3)  # None
m4 = re.search(r'good', 'hello world good morning')
print(m4)  # <re.Match object; span=(12, 16), match='good'>

# finditer 返回的结果是一个可迭代对象
# 可迭代对象里的数据是匹配到的所有结果,是一个re.Match类型的对象
m5 = re.finditer(r'x', 'ksdfjkxklkjfxxkljxlxlx')
print(isinstance(m3, Iterable))  # True
print(m5)  # <callable_iterator object at 0x0000023CC10B3B08>
for t in m5:
    print(t)

m6 = re.findall(r'x', 'ksdfjkxklkjfxxkljxlxlx')
print(m6)  # ['x', 'x', 'x', 'x', 'x', 'x']

m7 = re.fullmatch(r'hello', 'hello world')
m8 = re.fullmatch(r'hello world', 'hello world')
print(m7, m8)  # None <re.Match object; span=(0, 11), match='hello world'>

re.Match类的介绍

# 调用 re.match,re.search 或者re.finditer 结果进行遍历
# 拿到的内容都是 re.Match 类型对象
import re

# . 任意字符  * 出现任意次数
m = re.search(r'm.*a', 'kdfs3jmdfgha')
print(dir(m))
# print(m.pos, m.endpos)
print(m.span())  # 匹配到的结果字符串的开始和结束下标

# 获取匹配的字符串结果
print(m.group())  # mdfgha
# group 可以传参,表示第n个分组
print(m.group(0))  # mdfgha
# print(m.group(1))  # IndexError: no such group

# group 方法表示正则表达式的分组
# 1.在正则表达式里使用()表示一个分组
# 2.如果没有分组,默认只有一个分组
# 3.分组的下标从0开始
# 正则表达式有4个分组
m1 = re.search(r'(9.*)(0.*)(5.*7)', 'fsdf9nk0ji5ovxkhlj7sfiohljdjf')
print(m1)  # <re.Match object; span=(4, 19), match='9nk0ji5ovxkhlj7'>
print(m1.group())  # 第0组就是把整个正则表达式当做一个整体
print(m1.group(1))  # 9nk
print(m1.group(2))  # 0ji
print(m1.group(3))  # 5ovxkhlj7

print(m1.groups())  # ('9nk', '0ji', '5ovxkhlj7')
# 获取到分组组成的字典
print(m1.groupdict())   # {}
# (?P<name>表达式) 可以给分组起一个名字
m2 = re.search(r'(9.*)(?P<xxx>0.*)(5.*7)', 'fsdf9nk0ji5ovxkhlj7sfiohljdjf')
print(m2.groupdict())  # {'xxx': '0ji'}
print(m2.groupdict('xxx'))  # {'xxx': '0ji'}
print(m2.group(2))  # 0ji
print(m2.group('xxx'))  # 0ji
print(m2.span(2))  # (7, 10)

re.compile方法的使用

# compile 编译
# 在re模块里,可以使用 re.方法 调用函数,还可以调用 re.compile 得到一个对象
import re

m = re.compile(r'm.*a')
x = m.search('o3rjomjadas')
y = m.search('sdjflksjmsdfjjkafd')
print(x, y, sep=',')

正则修饰符的使用

import re

# 正则修饰符是对正则表达式进行修饰
# . 表示除了换行以外的任意字符
# re.S:让点 . 匹配换行
# re.I:忽略大小写
# re.M:让$能够匹配到换行
x = re.search(r'm.*a', 'sdfjmsj\nfafd', re.S)
# print(x)  # None
print(x)  # <re.Match object; span=(4, 10), match='msj\nfa'>

y = re.search(r'x', 'good Xyz', re.I)
print(y)

# \w:表示的是字母数字和_ +:出现一次及以上 $:以指定内容结尾
z = re.findall(r'\w+$', 'i am boy\n you are girl\n he is man', re.M)
# print(z)  # ['man']
print(z)  # ['boy', 'girl', 'man']

正则匹配规则

# 1.数字和字母都表示它本身
# 2.很多字母前面添加 \ 会有特殊含义
# 3.绝大多数标点符号都有特殊含义
# 4.如果想要使用标点符号,需要在前面加 \
import re

# 字母x,数字5表示它本身
re.search(r'x', 'hello xyz')
re.search(r'5', '23r49534')

# 字母d是普通的字符
print(re.search(r'd', 'good'))
# \d表示特殊含义,不再表示字母d
print(re.search(r'\d', 'good'))
print(re.search(r'\d', 'sduo4hkf'))

标点符号的特殊含义

import re

# \s 表示任意的空白字符
print(re.search(r'\s', 'hello world'))  # 空格
print(re.search(r'\n', 'hello\nworld'))  # 换行
print(re.search(r'\t', 'hello\tworld'))  # 制表符

# \S 表示非空白字符
print(re.search(r'\S', '\t\n   x'))  # <re.Match object; span=(5, 6), match='x'>

# 标点符号的使用

# ():用来表示一个分组
m = re.search(r'h(\d+)x', 'sh829xkflsa')
print(m.group())  # h829x
print(m.group(1))  # 829
m1 = re.search(r'\(.*\)', '(1+1)*3+5')
print(m1.group())  # (1+1)

# . 表示匹配除了换行以外的任意字符。如果想要匹配 . 需要使用 \.

# [] 用来表示可选项范围 [x-y]从x到y区间,包含x和y
# m2 = re.search(r'f[0-5]m', 'pdsf6m')
# m2 = re.search(r'f[0-5a-d]m', 'pdsf6m')
# m2 = re.search(r'f[0-5a-d]m', 'pdsfcm')
m2 = re.search(r'f[0-5a-dx]m', 'pdsfxm')
print(m2)

# | 用来表示或者
# [] 里的值表示的是区间, | 就是可选值
print(re.search(r'f(x|prz|t)m', 'pdsfprzm'))

# {} 用来限定出现的次数
# {n}:表示前面的元素出现n次
print(re.search(r'go{2}d', 'good'))
# {n,}:表示前面的元素出现n次以上
print(re.search(r'go{2,}d', 'goooood'))
# {,n}:表示前面的元素出现n次以下
print(re.search(r'go{,2}d', 'god'))
# {m,n}:表示前面的元素出现m到n次
print(re.search(r'go{3,5}d', 'goood'))

# *:表示前面的元素出现任意次数(0次及以上) 等价于 {0,}
print(re.search(r'go*d', 'goood'))

# +:表示前面的元素至少出现一次,等价于 {1,}
print(re.search(r'go+d', 'goood'))

# ?: 两种用法:
# 1.规定前面的元素最多只能出现一次,等价于{,1}
# 2.将贪婪模式转换成为非贪婪模式
re.search(r'go?d', 'gd')

# ^: 以指定的内容开头,在[]里还可以表示取反  $: 指定内容结尾
print(re.search(r'^a.*i$', 'ahkhi'))
print(re.search(r'[^0-9]+', 'he110'))

特殊字母的含义

import re
# 字母表示它本身,很多字母前面 \ 会有特殊含义
# \n:表示换行 \t:表示一个制表符 \s:空白字符 \S:非空白字符
# \d:表示数字 等价于 [0-9]
print(re.search(r'x\d+p', 'x243p'))
print(re.search(r'x[0-9]+p', 'x243p'))

# \D:表示非数字 等价于[^0-9]
print(re.search(r'\D+', 'he110'))
print(re.search(r'[^0-9]+', 'he110'))

# \w:表示数字、字母、下划线、非标点符号、中文
print(re.findall(r'\w+', 'hE110_p'))
print(re.findall(r'[0-9a-zA-Z_]+', 'hE110_p'))
print(re.findall(r'\w+', 'h+E-11.0_X*'))
print(re.findall(r'\w+', '大,+家..&好'))

# \W:\w 取反
print(re.findall(r'\W+', 'h+E-11.0_X*'))  # ['+', '-', '.', '*']

正则表达式的应用

# 判断用户输入的内容是否是数字,如果是数字转换成为数字类型
# \d+(\.?\d+)?
import re

num = input('请输入一段数字:')
if re.fullmatch(r'\d+(\.?\d+)?', num):
    print('是个数字')
    print(float(num))
else:
    print('不是一个数字')

# 以非数字开头,后面有   字母 数字 _ - 组成的长度4到14位的字符串
# 用户名匹配:r'^\D[a-z0-9A-Z_\-]{3,13}'

# 邮箱匹配:r'^([A-Za-z0-9_\-\.])+@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$'

# 匹配手机号  (现在已经不常用手机号验证,号段更新快,更改多,一般用短信验证码验证)
# r'^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[05-9]))\d{8}$'

# 匹配身份证号(有bug,2月的日期可能会出错,不是闰年,也写了29日不能判断正误)
# r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$'

正则替换

# 正则表达式作用是用来对字符串进行检索和替换
# 检索: match search fullmatch findall finditer
# 替换: sub
import re

t = '3ds34856f97ds6'
print(re.sub(r'\d', 'x', t))  # xdsxxxxxfxxdsx
print(re.sub(r'\d+', 'x', t))  # xdsxfxdsx


p = 'hello34good23'  # 把字符串里的数字 *2 ==> hello68good46


# 第一个参数是正则表达式
# 第二个参数是新字符或者一个函数
# 第三个参数是需要被替换的原字符串
def test(x):
    y = int(x.group(0))
    y *= 2
    return str(y)


# sub内部在调用 test 方法时,会把每一个匹配到的数据以 re.Match 的格式传参
print(re.sub(r'\d+', test, p))  # test函数是自动调用的

贪婪模式与非贪婪模式

import re

# 在Python的正则表达式里,默认是贪婪模式,尽可能多的匹配
# 在贪婪模式后面添加 ? 可以将贪婪模式转换成为非贪婪模式
m = re.search(r'm.*a', 'fmjauad')
print(m.group())  # mjaua

# 尽可能少的匹配
n = re.search(r'm.*?a', 'fmjauad')
print(n.group())  # mja

print(re.match(r'aa(\d+)', 'aa2343ddd').group(1))  # 2343
print(re.match(r'aa(\d+?)', 'aa2343ddd').group(1))  # 2
print(re.match(r'aa(\d+)ddd', 'aa2343ddd').group(1))  # 2343
print(re.match(r'aa(\d+?)ddd', 'aa2343ddd').group(1))  # 2343
print(re.match(r'aa(\d+?).*', 'aa2343ddd').group(1))  # 2
print(re.match(r'aa(\d??)(.*)', 'aa2343ddd').group(1))  # 空

练习

# 用户名匹配
# 1.用户名只能包含数字、字母和下划线
# 2.不能以数字开头
# 3.长度在6到16位
import re

username = input('请输入用户名:')
# x = re.match(r'^\D[a-zA-Z0-9_]{5,15}$', username)
x = re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]{5,15}', username)
if x is None:
    print('输入的用户名不符合规范')
else:
    print(x)
# 密码匹配
# 1.不能包含 !@#$%^&* 字符
# 2.必须以字母开头
# 3.长度在6到12位
import re

password = input('请输入密码:')
x = re.fullmatch(r'[a-zA-Z][^!@#$%^&*]{5,11}', password)
if x is None:
    print('密码不符合规范')
else:
    print(x)
demo.txt

1000phone hello python
mobiletrain 大数据
1000phone java
mobiletrain html5
mobiletrain 云计算
# 查找文件中以 1000phone 开头的语句,并保存到列表中
import re

x = []
try:
    with open('demo.txt', 'r') as file:
        # while True:
        #     content = file.readline().strip('\n')
        #     if not content:
        #         break
        #     if re.match(r'^1000phone', content):
        #         x.append(content)
        content = file.read()
        x = re.findall(r'1000phone.*', content)
except FileNotFoundError:
    print('文件打开失败')
print(x)
# ip地址检测 0.0.0.0 ~ 255.255.255.255
import re

num = input('请输入一个数字:')
x = re.fullmatch(r'((\d|[1-9]\d|1\d{2}|2([0-4]\d|5[0-5]))\.){3}(\d|[1-9]\d|1\d{2}|2([0-4]\d|5[0-5]))', num)
print(x)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值