Python正则表达式

正则表达式:一种文本模式匹配工具,Python中使用内置模块re实现正则功能

一、正则表达式作用

1.文本过滤:从大段文本中提取需要的内容

2.合法性校验:检查用户输入是否符合格式(如手机号、邮箱、数字类型等)

二、re模块核心函数

函数 作用 返回值 说明
re.search(pattern, string) 在整个字符串中搜索第一个匹配项 match对象或None 不要求从开头匹配
re.match(pattern, string) 从字符串开头开始匹配 match对象或None 相当于自动加^
re.findall(pattren, string) 查找所有匹配项 列表 如果有分组,只返回分组内容
re.finditer(pattern, string) 查找所有匹配项 迭代器 每个元素是match对象
re.sub(pattern, repl, string) 替换所有匹配项 新字符串 可用\1等引用分组
re.compile(pattern) 编译正则表达式 正则对象 重复使用时提升效率
python 复制代码
import re
msg = "hello, hunan; hello changsha"
print(re.findall(r"hello", msg))   # ['hello', 'hello']
print(re.search(r"hello", msg).group())  # hello
print(re.match(r"hello", msg).group())   # hello

三、match对象常用属性和方法

使用search或match返回的match对象

方法/属性 作用
group() 返回匹配到的完整字符串(参数默认为0)
group(n) 返回第n个捕获分组匹配的内容(n从1开始)
start() 匹配内容在原始字符串中的起始索引
end() 匹配内容在原始字符串中的结束索引(不包含)
span() 返回(start, end)元组

四、原始字符串(raw string)

正则表达式中包含很多反斜杠 \ ,为避免Python字符转义干扰,一般在字符串前加上r

1.原始字符串中\d就是两个字符 \ 和 d,不会被解释为转义

2.普通字符串中要表示 \d 需要写成 \\d

python 复制代码
# 匹配字符串中的 \t 两个字符(反斜杠+t)
print(re.search(r"o\\tsc", "hello\\tsc"))  # 匹配成功

五、正则表达式基本语法

1.字符类

①匹配方括号内任意单个字符字符

②支持范围:a-z0-9A-Za-z0-9

③取反:\^... 匹配不在括号内的任意字符

python 复制代码
re.findall("[pPfw]y", "I am learn python,hello wy")
# 结果:['py', 'wy'](匹配 py 或 Py 或 fy 或 wy)

2.或 |

①匹配左右任一表达式

②| 优先级较低,必要时用括号分组

python 复制代码
re.findall(r"changsha|wuhan", "welcome to changsha, welcome to wuhan")
# 结果:['changsha', 'wuhan']

3.占位符 .

匹配除换行符 \n 外的任意单个字符(re.S使其可以匹配换行)

python 复制代码
re.findall(".", "aA2*\t\n中文")  # 不包含 \n,其余都匹配

4.锚点 ^$

^:匹配字符串开头(多行模式下匹配每行开头,需re.M)

②$:匹配字符串结尾(多行模式下匹配每行结尾)

python 复制代码
re.findall(r"^p.thon", "pwthon python")   # 只匹配开头的 pwthon
re.findall(r"p.thon$", "pwthon python")   # 只匹配结尾的 python

5.快捷方式(预定义字符类)

符号 含义 等价写法
\d 数字 0-9
\D 非数字 \^0-9
\w 单词字符(字母、数字、下划线) A-Za-z0-9_
\W 非单词字符 \^A-Za-z0-9_
\s 空白字符(空格、\t、\n、\r、\f、\v) \\t\\n\\r\\f\\v
\S 非空白字符 \^ \\t\\n\\r\\f\\v
\b 单词边界(单词与空格/标点之间) 无等价
\B 非单词边界 无等价
\A 字符串开始(不受 re.M 影响) 类似 ^
python 复制代码
re.findall(r"\d", "hello 123")        # ['1','2','3']
re.findall(r"\bworld\b", "world# world123 worldxyz world abcworld")
# 结果:['world', 'world', 'world']  只匹配独立的 world

6.量词(重复次数)

符号 含义
* 前面的元素出现 0 次或多次
? 前面的元素出现 0 次或多次
+ 前面的元素出现 1 次或多次
{n} 前面的元素恰好出现 n 次
{n,} 至少出现 n 次
{n,m} 出现 n 到 m 次
python 复制代码
re.findall("py?", "python p pyy ps")   # ['py', 'p', 'py', 'p']
re.findall("py+", "python p pyy ps")   # ['py', 'pyy']
re.findall("py*", "python p pyy ps")   # ['py', 'p', 'pyy', 'p']
re.findall("py{2,4}", "pyyyy pyy p")   # ['pyyyy', 'pyy']

7.贪婪模式 vs 非贪婪模式

①贪婪模式(默认):量词尽可能多地匹配

②非贪婪模式:在量词后加 ?,匹配尽可能少

量词 非贪婪模式 说明
* *? 最少 0 次(可为空)
+ +? 最少 1 次
? ?? 最少 0 次
{n,m} {n,m}? 最少 n 次
python 复制代码
msg = "<div><p>hello</p></div><div><h1>world</h1></div>"
print(re.findall(r"<div>.*</div>", msg))
# 贪婪:匹配最长的 div 块 → ['<div><p>hello</p></div><div><h1>world</h1></div>']
print(re.findall(r"<div>.*?</div>", msg))
# 非贪婪:匹配最短的 div 块 → ['<div><p>hello</p></div>', '<div><h1>world</h1></div>']

六、分组与捕获

1.捕获分组(regex)

①将括号内的表达式作为一个整体

②匹配后会保存到内存,按左括号顺序编号1,2,3...

③可通过group(n)获取第n组内容

python 复制代码
msg = "tel:173-7572-2991"
ret = re.search(r'(\d{3})-(\d{4})-(\d{4})', msg)
print(ret.group(0))   # 173-7572-2991  (完整匹配)
print(ret.group(1))   # 173
print(ret.group(2))   # 7572
print(ret.group(3))   # 2991

2.非捕获分组(?:regex)

①只分组不捕获,不占用分组编号

②作用:使结构清晰,但不保存内容

python 复制代码
ret = re.search(r'(?:\d{3})-(\d{4})-(\d{4})', msg)
print(ret.group(1))   # 7572 (因为第一个分组是非捕获,编号从后面的开始)

3.向后引用 \1、\2...

①引用前面捕获分组匹配到的具体内容

②可用于匹配重复内容

python 复制代码
msg = "tel:173-7572-173"
ret = re.search(r'(\d{3})-(\d{4})-\1', msg)
print(ret.group())   # 173-7572-173  (最后的 173 与第一组相同)

# 非捕获分组后的引用
msg = "tel:173-7572-7572"
ret = re.search(r'(?:\d{3})-(\d{4})-\1', msg)
print(ret.group())   # 173-7572-7572  (\1 引用第一捕获组即 \d{4})

4.findall与分组的关系

①如果正则中包含捕获分组,findall只返回分组内容,不返回完整匹配

②若想返回完整匹配,可使用非捕获分组(?:...) 或去掉分组

python 复制代码
msg = "tel:173-7572-7572"
# 有捕获分组
print(re.findall(r'(\d{3})-(\d{4})-\d{4}', msg))  # [('173','7572')]
# 非捕获分组
print(re.findall(r'(?:\d{3})-(?:\d{4})-\d{4}', msg))  # ['173-7572-7572']

七、正则修饰符

修饰符 含义
re.M 多行模式,^$ 匹配每行的开头和结尾
re.I 忽略大小写
re.S 使 . 匹配包括换行符在内的任意字符
re.X 详细模式,允许在正则中添加注释和空白
re.A 使 \w\b 等只匹配 ASCII 字符
python 复制代码
msg = """
python
PyTHON
"""
print(re.findall("^python$", msg, re.M | re.I))
# 匹配两行,因为忽略大小写且每行单独匹配

八、零宽断言

零宽断言只匹配位置,不消耗字符,不会出现在匹配结果中

语法 名称 含义
(?<=exp) 正向后行断言 左边必须是 exp
(?<!exp) 负向后行断言 左边不能是 exp
(?=exp) 正向前行断言 右边必须是 exp
(?!exp) 负向前行断言 右边不能是 exp
python 复制代码
msg = "hello, world! welcome to changsha"

# 正向后行:匹配以 w 开头的字母串(不包括 w)
print(re.findall(r"(?<=w)[a-z]+", msg))   # ['orld', 'elcome']

# 负向后行:匹配 l,但左边不能是 e
print(re.findall(r"(?<!e)l", msg))        # 只匹配 world 中的 l(左边是 r)

# 正向前行:匹配逗号前的字母串
print(re.findall(r"[a-z]+(?=,)", msg))    # ['hello']

# 负向前行:匹配后面不是逗号的字母串(按 findall 逐个字符找连续字母)
print(re.findall(r"[a-z]+(?!,)", msg))    # ['hell', 'world', 'welcom', 'to', 'changsh'] 等
相关推荐
wangchen_02 天前
C++正则表达式
开发语言·c++·正则表达式
Patrick在香港3 天前
Python正则表达式实战:解析和验证香港身份证、车牌、电话格式
开发语言·python·正则表达式
吴声子夜歌5 天前
正则指引——Ruby
开发语言·正则表达式·ruby
吴声子夜歌5 天前
正则指引——Golang
开发语言·golang·正则表达式
吴声子夜歌6 天前
正则指引——PHP
开发语言·正则表达式·php
吴声子夜歌8 天前
正则指引——断言
正则表达式
吴声子夜歌8 天前
正则指引——匹配原理
java·正则表达式
吴声子夜歌9 天前
正则表达式——环视
开发语言·正则表达式