python基础-07-模式匹配与正则表达式

文章目录

【README】

本文总结自《python编程快速上手-让繁琐工作自动化》第7章,非常棒的一本书,墙裂推荐;


【7】用正则表达式查找文本

【7.1】匹配Regex对象

1)创建正则表达式对象

python 复制代码
phonenumRegExpr = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')

2)Regex对象的search()方法查找传入的字符串,返回该正则表达式所有的匹配;

  • 如果没有找到匹配,返回None;
  • 如果找到了匹配,返回Match对象;
    • Match 对象的group()方法,返回被查找字符串中实际匹配的文本(分组)
python 复制代码
import re

phonenumRegExpr = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
matchObj = phonenumRegExpr.search('Tom\'s number is 123-456-7890')
print('matched = ' + matchObj.group()) # matched = 123-456-7890

【7.2】正则表达式匹配更多模式

【7.2.1】利用括号分组

python 复制代码
print('\n\n==== 利用括号分组')
phonenumRegExpr = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
matchObj = phonenumRegExpr.search('Tom\'s number is 123-456-7890')
print(matchObj.group()) # 123-456-7890
print(matchObj.group(0)) # 123-456-7890
print(matchObj.group(1)) # 123
print(matchObj.group(2)) # 456-7890

1)遍历分组

python 复制代码
# 遍历分组(分组实际上是一个元组)
print('\n\n===遍历分组(分组实际上是一个元组)')
groupTuple = matchObj.groups()
for group in groupTuple:
    print(group)
# 123
# 456-7890

2)使用多重赋值读取正则表达式分组

python 复制代码
print('\n\n===使用多重赋值读取正则表达式分组')
first, second = matchObj.groups()
print(first, second, sep=',') # 123,456-7890

3)正则表达式中的特殊字符需要转译(使用倒斜杠或反斜杠转译 \):包括

python 复制代码
# 正则表达式中的特殊字符需要转移 包括
# . ^ $ * + ? { } [ ] \ | ( )
# 转译写法: \. \^ \$ \* \+ \? \{ \} \[ \] \\ \| \( \)

【7.2.2】用管道匹配多个分组

1)字符 | 称为管道(或运算),希望匹配多个表达式中的一个时,可以使用它;

python 复制代码
# 字符|称为管道, 希望匹配许多表达式中的一个时,就可以使用它
print('\n\n===用管道匹配多个分组')
heroRegExpr = re.compile(r'zhangsan|lisi')
print(heroRegExpr.search('zhangsan and lisi').group()) # zhangsan
print(heroRegExpr.search('lisi and zhangsan').group()) # lisi

# 使用管道来匹配多个模式中的一个,这些模式可以是正则表达式中的一部分
print('\n\n===使用管道来匹配多个模式中的一个')
tempRegExpr01 = re.compile(r'Zhangsan(01|02|03)')
print(tempRegExpr01.search('Zhangsan01 is a student').group()) # Zhangsan01
print(tempRegExpr01.search('Zhangsan01 is a student').group(0)) # Zhangsan01
print(tempRegExpr01.search('Zhangsan01 is a student').group(1)) # 01

【7.2.3】用问号实现可选匹配

1) 用?问号匹配0次或1次(如果匹配真正的?号,使用?)

python 复制代码
print('\n\n===用问号?实现可选匹配 ?匹配0次或1次')
regExpr03 = re.compile(r'zhangsan(110)?')
print(regExpr03.search('zhangsan111').group()) # zhangsan
print(regExpr03.search('zhangsan1100').group()) # zhangsan110

【7.2.4】用*星号匹配0次或多次

1)用*星号匹配0次或多次(如果匹配真正的*号,使用*)

python 复制代码
print('\n\n===用*星号匹配0次或多次')
regExpr04 = re.compile(r'Abc(wo)*man')
print(regExpr04.search('my name is Abcwoman').group()) # Abcwoman
print(regExpr04.search('my name is Abcman').group()) # Abcman
print(regExpr04.search('my name is Abcwowowoman').group()) # Abcwowowoman

【7.2.5】用+加号匹配一次或多次

1)用+加号匹配一次或多次 (如果匹配真正的+号,使用+)

python 复制代码
print('\n\n===用+加号匹配一次或多次')
regExpr05 = re.compile(r'Abc(wo)+man')
print(regExpr05.search('my name is Abcwoman').group()) # Abcwoman
print(regExpr05.search('my name is Abcman')) # 匹配失败,返回None, 调用None.group()报错
print(regExpr05.search('my name is Abcwowowoman').group()) # Abcwowowoman

【7.2.6】用花括号匹配特定次数

1)用花括号匹配特定次数 (ha){3} 匹配 'HaHaHa' (ha){3,5} 匹配最少3个ha且最多5个ha的字符串

python 复制代码
print('\n\n===用花括号匹配特定次数')
regExpr06 = re.compile(r'Abc(wo){3,5}man')
print(regExpr06.search('my name is Abcwoman')) # None 调用None的group()方法会报错
print(regExpr06.search('my name is Abcwowowoman').group()) # Abcwowowoman
print(regExpr06.search('my name is Abcwowowowoman').group()) # Abcwowowowoman
print(regExpr06.search('my name is Abcwowowowowoman').group()) # Abcwowowowowoman
print(regExpr06.search('my name is Abcwowowowowowoman')) # None 调用None的group()方法会报错

【7.3】贪心与非贪心匹配

1)python的正则表达式默认是贪心的,即尽可能匹配最长的字符串;

  • 花括号的非贪心是匹配最短的字符串,但需要再结束花括号前跟着一个问号;
python 复制代码
print('\n\n===贪心与非贪心匹配')
# 贪心 (匹配最长)
greedyHaRegExpr = re.compile(r'(Ha){3,5}')
print(greedyHaRegExpr.search('HaHaHaHaHa').group()) # HaHaHaHaHa

# 非贪心 (匹配最短)
nonGreedyHaRegExpr = re.compile(r'(Ha){3,5}?')
print(nonGreedyHaRegExpr.search('HaHaHaHaHa').group()) # HaHaHa

【7.4】findAll()方法

1)无分组的正则表达式的findall()方法:返回一个字符串列表

python 复制代码
print('\n\n===正则表达式的findall()方法')
phonenumRegExpr = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
print(phonenumRegExpr.findall('home: 123-456-7890 work:111-222-3333'))
# ['123-456-7890', '111-222-3333']

2)有分组的正则表达式的findall()方法:返回匹配的元组列表

python 复制代码
print('\n\n===有分组的正则表达式的findall()方法:返回元组列表')
phonenumRegExpr = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
print(phonenumRegExpr.findall('home: 123-456-7890 work:111-222-3333'))
# [('123', '456', '7890'), ('111', '222', '3333')]

【7.5】正则表达式缩写字符分类

1)用\d表示任何数字, 等价于 (0|1|2|3|4|5|6|7|8|9)

2)用[a-zA-Z]匹配字母;

3)字符分类如下:

【7.6】插入字符^与美元字符$

1)插入字符与美元字符

  • 插入字符^ 表示匹配发生在输入字符串的开头
  • 美元字符$ 表示匹配发生在输入字符串的结尾

2)同时使用插入字符与美元字符: 表示整个字符串必须匹配该模式,也就是说,只匹配该字符串的某个子集是不够的;

【代码示例】插入字符^ 表示匹配发生在输入字符串的开头

python 复制代码
print('\n\n===插入字符^ 表示匹配发生在输入字符串的开头')
startWithHello = re.compile('^Hello')
print(startWithHello.search('Hello Wolrd').group()) # Hello
print(startWithHello.findall('Hello Wolrd'))  # ['Hello']
print(startWithHello.search('Hello Wolrd') == None)  # False

【代码示例】美元字符$ 表示匹配发生在输入字符串的结尾

python 复制代码
print('\n\n===美元字符$ 表示匹配发生在输入字符串的结尾')
endWithNumber = re.compile(r'\d$')
print(endWithNumber.search('zhangsan001').group()) # 1

【7.7】通配字符

【7.7.1】点星字符(.*) 匹配所有字符

python 复制代码
print('\n\n===通配字符')
# 点星字符(.*) 匹配所有字符
pointStartRegExpr = re.compile(r'.*')
print(pointStartRegExpr.findall('the cat sat on the flat sofa')) # ['the cat sat on the flat sofa', '']

【7.7.2】句点字符(.) 匹配换行符之外的所有字符

python 复制代码
# 句点字符(.) 匹配换行符之外的所有字符
pointRegExpr = re.compile(r'.at')
print(pointRegExpr.findall('the cat sat on the flat sofa')) # ['cat', 'sat', 'lat']

【7.7.3】句点字符(.) 匹配所有字符,包括换行符

python 复制代码
# 传入 re..DOTALL 作为 re.compile()的第2个参数,让句点可以匹配所有字符,包括换行符
newLineRegExpr = re.compile(r'.*', re.DOTALL)
print(newLineRegExpr.search('the cat sat on the flat sofa, \n and i sat on the bed yesterday.'))
print(newLineRegExpr.findall('the cat sat on the flat sofa, \n and i sat on the bed yesterday.'))
# ['the cat sat on the flat sofa, \n and i sat on the bed yesterday.', '']

【7.8】正则表达式符号复习

【7.9】不区分大小写匹配

1)不区分大小写匹配: 把 re.IGNORECASE 或 re.I 作为 re.compile方法的第2个参数

【7.10】 用sub()方法替换字符串 (sub=substitute)

python 复制代码
substituteExpr = re.compile(r'zhangsan')
print(substituteExpr.sub('lisi', 'zhangsan is a student.'))
# lisi is a student.

【7.11】组合使用 re.IGNORECASE re.DOTALL re.VERBOSE

python 复制代码
composedExpr = re.compile(r'zhangsan \n and lisi', re.IGNORECASE | re.DOTALL | re.VERBOSE)
print(composedExpr.search('zhangsan \n and LISI are friends'))  # None
相关推荐
唐古乌梁海9 分钟前
【Django】教程-3-数据库相关介绍
python·django
vener_19 分钟前
基于Flask的通用登录注册模块,并代理跳转到目标网址
后端·python·flask
Lonwayne20 分钟前
当编程语言有了人格
java·javascript·c++·python·php
love729234ming24 分钟前
MySQL Explain 分析 SQL 执行计划
数据库·sql·mysql
聪明的一休丶24 分钟前
MCP Server 实现一个 天气查询
python·llm·aigc·mcp
nlog3n1 小时前
MySQL 常见面试问题总结
java·数据库·mysql·面试
字节跳动开源1 小时前
MySQL遇到AI:字节跳动开源 MySQL 虚拟索引 VIDEX
人工智能·mysql·开源·虚拟索引技术·解耦架构
图书馆钉子户1 小时前
django orm的优缺点
后端·python·django
linuxxx1101 小时前
django报错:RuntimeError: populate() isn‘t reentrant
后端·python·django
搬码红绿灯2 小时前
数据库——MySQL字符、日期函数
数据库·mysql