十四、正则表达式

学习目标

  • 能够描述什么是正则表达式
  • 能够使用re模块查找指定正则格式的字符串
  • 能够说出match,search,findall和finditer方法的区别
  • 能够说出re.Match类的常见属性和方法作用
  • 能够说出常见的正则修饰符
  • 能够说出常见的正则表达模式
    • 单字修饰符
    • 限定修饰符
    • 边界修饰符
  • 能够说出贪婪模式和非贪婪模式的区别
  • 能使用非贪婪模式进行正则匹配

一、正则表达式的介绍

  • 正则表达式是一个特殊的字符序列,计算机科学的一个概念。通常被用来检索、替换哪些符合某个模式(规则)的文本
  • 许多程序设计语言都支持利用正则表达式进行字符串操作。在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用 re模块。re模块使用 Python 语言拥有全部的正则表达式功能
  • 特点:
  1. 灵活性、逻辑性和功能性非常强
  2. 可以迅速地用极简单的方式达到字符串的复杂控制
  3. 对于刚接触的人来说,比较晦涩难懂
# 用来处理字符串,对字符串进行检索和替换的
# 1. 查找    2. 替换
import re

x = 'hello\\nworld' # hello\nworld
# 在正则表达式里,如果想要匹配一个 \ 需要使用 \\\\

# 第一个参数就是正则匹配规则
# 第二个参数表示需要匹配的字符串

# m = re.search('\\\\', x) # match 和 search

# 还可以在字符串前加入一个 r,\\ 就表示 \
m = re.search(r'\\', x)

# search 和 match 方法的执行结果是一个Match类型的对象
print(m) # <re.Match object;span=(5, 6), match='\\'>

二、正则查找相关的方法

# 查找相关的方法
# match 和 search:
# 共同点:1. 只对字符串查询一次  2. 返回值类型都是 re.Match 类型的对象(没有匹配上则返回None)
# 不同点:match 是从头开始匹配,一旦匹配失败,就会方法返回 None;search是在整个字符串里匹配
查找字符串,返回结果是一个 re.Match 对象

# finditer:查找到所有的匹配数据放到一个可迭代对象里(各数据是 re.Match 对象)

# findall:把查找到的所有的字符串放到一个列表里

# fullmatch:完整匹配,字符串需要完全满足正则规则才会有结果,否则就是None


from connections.adc import Iterable
import re
m1 = re.match(r'good','hello world good morning')
print(m1) # None

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

# finditer 返回的结果是一个可迭代对象
# 可迭代对象里的数据是匹配到的所有结果,是一个 re.Match 类型的对象
m3 = re.finditer(r'x','fhquhfnxpkmapixok1i')
print(isinstance(m3, Iterable)) # True

for t in m3:
    print(t)    

m4 = re.findall(r'x\d+','xqofho1cxhjax123x14')
print(m4) # 以x开头且带数字元素组成的列表

m5 = re.fullmatch(r'hello world', 'hello world')

三、re.Match类

当我们调用 re.match 方法、re.search 方法、或者对 re.finditer 方法的结果进行迭代时,拿到的数据类型都是 re.Match 对象

import re

m = re.search(r'm,'sdafhiwmkom')

# 匹配到的结果字符串的开始和结束下标
print(m.span()) 

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

# group方法表示正则表达式的分组
# 1. 在正则表达式里使用()表示一个分组
# 2. 如果没有分组,默认只有一组
# 3. 分组的下标从0开始

# 正则表达式有 四个 分组
m1 = re.search(r'(9.*)(0.*)(5.*7)', 'da9fi0riel5kfda7ifsdaiferit')
# 分组0:就是把整个正则表达式当做一个整体
# m1.group() 默认就是拿分组0的内容
# 分组1:就是第一个()的正则匹配的内容
# ...

 # 将各分组(除分组0)的内容组合成一个元组返回
print(m1.groups())

# groupdict 作用是获取到分组组成的字典
print(m1.groupdict()) # {}

# (?P<name>表达式)   可以给分组起一个名字
m2 = re.search(r'(9.*)(?P<xxx>0.*)(5.*7)', 'da9fi0riel5kfda7ifsdaiferit')
print(m2.groupdict()) # {'xxx':'0riel'}

# 可以通过分组名或分组的下标获取到分组里匹配到的字符串
print(m2.group('xxx')) # 0riel
print(m2.group(2)) # 0riel

四、re.compile 方法的使用

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

import re

# 可以直接调用 re.search 方法
m = re.search(r'm.*a','o3rjomjadas')
print(m)

r = re.compile(r'm.*a')
x = r.search('o3rjomjadas')
print(x)

五、正则修饰符

import re
# 正则修饰符是对正则表达式进行修饰的
# re.S:让 . 匹配换行
# re.I:忽略大小写
# re.M:让 $ 能匹配上换行

# .  表示除了换行以外的任意字符
x = re.search(r'm.*a','sdfmo\nejoasdl', re.S)
print(x)

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') # ['boy', 'girl', 'man']

六、正则表达式

6.1 正则表达式规则

# 1. 数字和字母都表示它本身
# 字母 x 表示它本身
re.search(r'x', 'hello xyz')
re.search(r'5', '81245asfkl')

# 2. 很多字母前面添加 \ 会有特殊含义(重点)
re.search(r'd', 'good') # 字母 d 是普通的字符
re.search(r'\d', 'good') # \d 有特殊含义,不再表示字母 d

# 3. 绝大多数有特殊含义(重点)
re.search('+', '1+2') # 不能直接使用,+ 有特殊含义

# 4. 如果想要使用标点符号,需要加转移字符 \
re.search(r'\+', '1+2')

6.2 标点符号的特殊含义

  • 标点符号特殊字符
    所谓特殊字符,就是一些有特殊含义的字符。若要匹配这些特殊字符,必须首先使字符 “转义”,即,将反斜杠字符 \ 放在它们前面。下表列出了正则表达式中的特殊字符
标点符号特殊字符描述
()标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \ (和 \ )
.匹配除换行符 \n 之外的任何单字符。要匹配.,请使用.
[标记一个中括号表达式的开始。要匹配 [ ,请使用 \ [
|将下一个字符标记为特殊字符、或原义字符、或向后引用、或八进制转义符。例如,‘n’匹配字符 ‘n’。’\n’匹配换行符,\ 匹配 \ ,而 ( 则匹配 (
{标记限定符表达式的开始。要匹配{,请使用{
|指明两项之间的一个选择。要匹配 | 请使用 |
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')) # x

# 标点符号的使用:
# ():用来表示一个分组
m = re.search(r'h(\d+)x', 'sh829xkflsa')
print(m.group(1)) # 829
# 如果要表示括号,需要使用 \
m1 = re.search(r'\(.*\)', '(1+1)*3+5')
print(m1.group())

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

# [] 用来表示可选项 [x-y]从x到y的区间,包含x和y
m2 = re.search(r'f[0-5]m','pdsf3m')
# m2 = re.search(r'f[a-d]m','padsfcm')
# +:一次或多次匹配前面的正则特殊符匹配的单字符
# m2 = re.search(r'f[0-5]+m','padsf4423m')
# 此处[]内的0-5与a-d与x是或的关系
# m2 = re.search(r'f[0-5a-dx]+m','padsfxm')
print(m2.group()) # f3m

# | 用来表示或者   和   [] 有一定的相似,但是有区别
# [] 里的值表示的是区间,而且是单个字符
# | 就是可选值,可以出现多个值(如:x与prz与t并列)
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'), 'gooooood')
# {,n}:表示前面的元素出现 n 次及以下
print(re.search(r'go{2,}d'), 'god'
# {m,n}:表示前面的元素出现m到n次
print(re.search(r'go{3,5}d'), 'go0000d'

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

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

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

# ^:以指定内容开头    $:指定内容结尾
print(re.search(r'^a.*i$', 'aofi'))

6.3 字母的特殊含义

  • 特殊字母
特殊字母字符描述
\d匹配一个数字字符。等价于 [0-9]
[0-9]匹配任何单数字。等价于 \d
\D匹配一个非数字字符。等价于 [^0-9]
[a-z]匹配任何小写字母
[A-Z]匹配任何大写字母
[a-zA-Z0-9]匹配任何字母及数字。等价于 \w
\w、_匹配包括下划线的任何单一字符(即数字、字母以及 _)。等价于 [A-Za-z0-9_]
# 字母表示它本身,很多字母前面  \  会有特殊含义

# \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:表示数字、字母以及 _以及中文等(的单一字符) 等价于 [0-9a-zA-Z_]
print(re.findall(r'\w+', 'h+E-11.0_X*'))

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

七、正则替换

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

# 将单个数字替换为x
t = 'afo2dlkf23af245qou3095'
print(re.sub(r'\d','x',t))

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

# 第一个参数是正则表达式
# 第二个参数是新字符或者一个函数
# 第三个字符需要被替换的原来的字符串
# sub内部再调用 test 方法时,会把每一个匹配到的数据以 re.Match 的格式传参
print(re.sub(r'\d+', lambda x: str(2 * int(x.group())), p))

八、贪婪模式和非贪婪模式

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

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

x1 = re.match(r'aa(\d+)', 'aa2343ddd')
print(x1.group(0)) # aa2343
print(x1.group(1)) # 2343

x2 = re.match(r'aa(\d+?)', 'aa2343ddd')
print(x2.group(0)) # aa2
print(x2.group(1)) # 2

x3 = re.match(r'aa(\d+)ddd', 'aa2343ddd')
print(x3.group(0)) # aa2343ddd
print(x3.group(1)) # 2343

x4 = re.match(r'aa(\d+?)ddd', 'aa2343ddd')
print(x4.group(0)) # aa2343ddd
print(x4.group(1)) # 2343

x5 = re.match(r'aa(\d+?).*', 'aa2343ddd')
print(x5.group(0)) # aa2343ddd
print(x5.group(1)) # 2

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ModelBulider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值