【Python中的正则表达式 | re模块】

正则表达式(Regular Expression,通常简写为regex或regexp)是一种强大的文本处理工具,它使用一种特定的模式来描述和匹配字符串。正则表达式可以用于搜索、替换和验证文本中的特定字符序列

简单来说,可以理解为正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配

一、基本概念和常见元素

1、基本元素

  • 字符类:匹配方括号中的任意字符。例如,[abc] 匹配 "a"、"b" 或 "c"。
  • 范围:使用连字符 - 来表示字符范围。例如,[a-z] 匹配任何小写字母。
  • 否定字符类:在字符类前加上 ^ 符号可以匹配不在该字符类中的任意字符。例如,[^a-z] 匹配任何非小写字母的字符。
  • 元字符:具有特殊含义的字符,如 .(匹配任意字符,除了换行符)、*(匹配前面的元素零次或多次)、+(匹配前面的元素一次或多次)、?(匹配前面的元素零次或一次)等。
  • 锚点:用于指定匹配的位置,如 ^(匹配字符串的开头)和 $(匹配字符串的结尾)。

2、分组和引用

  • 圆括号:用于分组,并捕获匹配的子字符串
  • 反向引用:使用 \1、\2 等来引用之前捕获的分组。

3、修饰符和标志

  • 多行模式:使 ^ 和 $ 分别匹配每一行的开头和结尾,而不是整个字符串的开头和结尾。
  • 忽略大小写:使匹配时不区分大小写。
  • 全局搜索:搜索整个字符串中的所有匹配项,而不是只找到第一个就停止。

4、常见应用

  • 验证:检查字符串是否符合特定的格式或规则,如电子邮件地址、电话号码等。
  • 搜索和替换:在文本中查找特定的模式,并用其他文本替换它。
  • 分割字符串:使用正则表达式作为分隔符来分割字符串。

示例:

python 复制代码
import re

text = "There are 123 apples and 456 oranges."
pattern = r'\d+'  # 匹配一个或多个数字

matches = re.findall(pattern, text)
print(matches)  # 输出: ['123', '456']

示例中, r'\d+' 是一个正则表达式,其中 \d 匹配任意数字, + 匹配前面的元素(即数字)一次或多次。re.findall() 函数用于在文本中查找所有匹配该正则表达式的子字符串。

二、python 正则表达式 re模块

re 模块使 Python 语言拥有全部的正则表达式功能。这个模块提供了一系列函数和方法,用于匹配和操作字符串。接下来将学习re模块的处理函数。

1、re模块的基本函数

python 复制代码
>>> import re
>>> dir(re)
['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 
'Match', 'NOFLAG', 'Pattern', 'RegexFlag', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 
'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '_MAXCACHE2', '__all__', '__builtins__',
 '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 
 '__path__', '__spec__', '__version__', '_cache', '_cache2', '_casefix',
  '_compile', '_compile_template', '_compiler', '_constants', '_parser',
   '_pickle', '_special_chars_map', '_sre', 'compile', 'copyreg', 'enum',
    'error', 'escape', 'findall', 'finditer', 'fullmatch', 'functools', 
    'match', 'purge', 'search', 'split', 'sub', 'subn', 'template']
>>>

和其他模块一样,在使用re模块来处理正则表达式时,要先导入 re 模块

python 复制代码
import re

2、re模块函数使用

正则表达式的语法和功能非常强大和灵活,可以通过学习更多的元字符、量词、边界匹配来扩展正则表达式的知识。
(1)re.match()

从字符串的起始位置匹配一个模式,如果匹配成功,返回一个匹配对象;否则返回None

语法:

python 复制代码
re.match(pattern, string, flags=0)

参数说明--

pattern:匹配的正则表达式

string :要匹配的字符串。

flags :标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

匹配对象方法:可使用 group(num)groups() 匹配对象函数来获取匹配表达式。

  • group(num=0) 匹配的整个表达式的字符串,group()可一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
  • groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

示例如下:

python 复制代码
import re

line = "Cats are smarter than dogs"

matchObj = re.match(r'(.*) are (.*?) than (.*)', line)
if matchObj:
    print("matchObj.group() : ", matchObj.group())  #输出 Cats are smarter than dogs
    print("matchObj.groups() : ", matchObj.groups()) #输出 ('Cats', 'smarter', 'dogs')
    print("matchObj.group(1) : ", matchObj.group(1)) #输出 Cats
    print("matchObj.group(2) : ", matchObj.group(2)) #输出 smarter
    print("matchObj.group(3) : ", matchObj.group(3)) #输出dogs

else:
    print("No match!!")

以上示例,正则表达式:r'(.*) are (.*?) than (.*)'

其中 (.*):匹配任意数量的任意字符(除了换行符),并将它们捕获到第一个组中。
(.*?):匹配任意数量的任意字符(除了换行符),但尽可能少地匹配(非贪婪模式),并将它们捕获到第二个组中。

(2)re.search()

扫描整个字符串,返回第一个成功匹配的对象。

语法:

python 复制代码
re.search(pattern, string, flags=0)
  • re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None。
  • re.search匹配整个字符串,直到找到一个匹配。
python 复制代码
import re
print(re.match('hello', 'hello.python.com').span())  # 在起始位置匹配   输出:(0, 5)
print(re.match('com', 'hello.python.com'))         # 不在起始位置匹配   输出:None

print(re.search('hello', 'hello.python.com').span())  # 在起始位置匹配   输出:(0, 5)
print(re.search('com', 'hello.python.com').span())    # 不在起始位置匹配  输出:(13, 16)

(3)re.findall()

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

语法:

python 复制代码
findall(string, pos, endpos])

参数说明:

string : 待匹配的字符串。

pos : 可选参数,指定字符串的起始位置,默认为 0。

endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

示例:

python 复制代码
import  re
pattern = re.compile(r'\d+') # 匹配一个或多个数字
text= "I have 100 leomon trees and 20 rivers"
findall= pattern.findall(text)
findall1= pattern.findall(text,0,10)
print("findall:",findall)  #输出:findall: ['100', '20']
print("findall1:",findall1) #输出:findall1: ['100']

(4)re.finditer()

找到字符串中所有匹配的部分,并返回一个迭代器,产生匹配对象。

语法:

python 复制代码
re.finditer(pattern, string, flags=0)

示例:

python 复制代码
import  re
pattern = re.compile(r'\d+') # 匹配一个或多个数字
text= "I have 100 leomon trees and 20 rivers"
findall= pattern.finditer(text)
findall1= pattern.finditer(text,0,10)
for match in findall:
    print (match.group() )
for match in findall1:
    print (match.group() )

运行结果:

python 复制代码
100
20
100

(5)re.sub():检索和替换

在字符串中查找匹配正则表达式的部分,并用另一个字符串替换它们。

语法:

python 复制代码
re.sub(pattern, repl, string, count=0, flags=0)

参数说明:

pattern : 正则中的模式字符串。

repl : 替换的字符串,也可为一个函数。

string : 要被查找替换的原始字符串。

count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

(6)re.split():分割

split 方法按照能够匹配的子串将字符串分割后返回列表.

语法:

python 复制代码
re.split(pattern, string, maxsplit=0, flags=0])

参数说明:

  • pattern, string同上。
  • maxsplit 分隔次数,maxsplit=1 分隔一次,默认为
    0,不限制次数。
  • flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

(7)re.compile():

编译正则表达式,根据一个模式字符串和可选的标志参数生成一个正则表达式( Pattern )对象。

即:预编译一个正则表达式对象,然后重复使用它。

该对象拥有一系列方法用于正则表达式匹配、搜索、替换等操作。

语法:

python 复制代码
re.compile(pattern, flags=0)

① pattern : 一个字符串形式的正则表达式

② flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

  • re.I 忽略大小写
  • re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
  • re.M 多行模式
  • re.S即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
  • re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
  • re.X 为了增加可读性,忽略空格和 # 后面的注释

编译后的Pattern对象可以使用的方法包括match()、search()、findall()、finditer()、sub()、split()等

示例:

python 复制代码
import re

# 编译一个正则表达式
pattern = re.compile(r'\d+')  # 匹配一个或多个数字

# 使用编译后的正则表达式对象进行匹配
text = "123 apples and 456 oranges."

# 使用match方法从字符串的起始位置匹配
match = pattern.match(text)
if match:
    print("Match at start:", match.group()) #输出 Match at start: 123
else:
    print("No match at start.")

# 使用search方法在整个字符串中搜索匹配项
search = pattern.search(text)
if search:
    print("Match found:", search.group()) # 输出: Match found: 123
else:
    print("No match found.")

# 使用findall方法找到所有匹配项
matches = pattern.findall(text)
print("All matches:", matches)  # 输出: All matches: ['123', '456']

compile()函数的好处:可将正则表达式的编译和匹配操作分开,多次重用编译后的正则表达式对象,提高性能。使代码更清晰、更易于维护。

(8)修饰符和标志

在编译正则表达式时,可以使用一些标志来改变匹配的行为。例如,re.IGNORECASE或re.I用于忽略大小写匹配。

示例如下:

python 复制代码
import re

print("----re.match()匹配----")
pattern = r'\d+'  #匹配一个或多个数字
text = "123 apples and 456 oranges"
match = re.match(pattern, text)
if match:
    print("Found:", match.group())  # 输出: Found: 123


print("----re.search()扫描----")
match = re.search(pattern, text)
if match:
    print("Found:", match.group())  # 输出: Found: 123


print("----re.findall()函数----")#找到字符串中所有匹配的部分,并返回一个列表
matches = re.findall(pattern, text)
print(matches)  # 输出: ['123', '456']


print("----re.finditer()函数----")
#找到字符串中所有匹配的部分,并返回一个迭代器,产生匹配对象。
matches = re.finditer(pattern, text)
for match in matches:
    print(match.group())  # 分别输出: 123 和 456


print("----re.sub()替换----")
new_text = re.sub(r'\d+', 'XXX', text)
print(new_text)  # 输出: XXX apples and XXX oranges


print("----re.split()分割----")
words = re.split(r'\d+', text)
print(words)  # 输出: ['', ' apples and ', ' oranges']


print("----re.compile()预编译----")
compiled_pattern = re.compile(r'\d+')
matches = compiled_pattern.findall(text)
print(matches)  # 输出: ['123', '456']


print("----re.IGNORECASE或re.I用于忽略大小写匹配----") #修饰符和标志
pattern = re.compile(r'apple', re.IGNORECASE)
match = pattern.search('There is an Apple on the table.')
if match:
    print("Found:", match.group())  # 输出: Found: Apple

三、应用

'(?P...)' 分组匹配

示例1:日期"The date is 2024-04-18."

python 复制代码
import re

# 定义一个包含日期的字符串
date_string = "The date is 2023-03-15."
# 使用命名分组来匹配日期
pattern = r"The date is (?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})."
# 执行匹配
match = re.search(pattern, date_string)
# 如果匹配成功,打印命名分组的值
if match:
    print("match.group:", match.group())
    print("group-Year:", match.group("year"))
    print("group-Month:", match.group("month"))
    print("group-Day:", match.group("day"))

    print("match.groups:", match.groups())
    print("groups-Year:", match.groups("year"))
    print("groups-Month:", match.groups("month"))
    print("groups-Day:", match.groups("day"))

    print("match.groupdict:", match.groupdict())

else:
    print("No match found.")

运行结果:

python 复制代码
match.group: The date is 2023-03-15.
group-Year: 2023
group-Month: 03
group-Day: 15
match.groups: ('2023', '03', '15')
groups-Year: ('2023', '03', '15')
groups-Month: ('2023', '03', '15')
groups-Day: ('2023', '03', '15')
match.groupdict: {'year': '2023', 'month': '03', 'day': '15'}

示例2:识别身份证ID

在Python的re模块中,当使用命名分组(即(?P...)语法)进行正则表达式匹配时,匹配对象会提供一个名为groupdict()的方法。这个方法返回一个字典,其中的键是命名分组的名称,值是相应分组匹配到的字符串。这对于提取和访问匹配到的命名分组非常有用。

python 复制代码
import re

id = '4102211990xxxxxxxx'
res = re.search(r'(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})', id[:10])
if res:
    print(res.groupdict())#输出{'province': '410', 'city': '221', 'born_year': '1990'}
else:
    print("No match found.")

or

python 复制代码
import re
id = '4102211990xxxxxxxx'
res = re.search(r'(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',id)
print(res.groupdict())
相关推荐
郜太素1 分钟前
PyTorch 中神经网络相关要点(损失函数,学习率)及优化方法总结
人工智能·pytorch·python·深度学习·神经网络·学习
L_cl5 分钟前
【Python 算法零基础 2.模拟 ④ 基于矩阵】
python·算法·矩阵
YUJIANYUE12 分钟前
PHP黑白胶卷底片图转彩图功能 V2025.05.15
php
玉笥寻珍12 分钟前
web安全渗透测试基础知识之登录绕过篇
python·安全·web安全·网络安全·威胁分析
为自己_带盐22 分钟前
浅聊一下数据库的索引优化
开发语言·数据库·php
Eric.Lee202125 分钟前
conda 输出指定python环境的库 输出为 yaml文件
linux·python·conda
PAQQ30 分钟前
【python】windows实现与k230使用socket通信并传输文件
python·stm32·单片机
胡耀超1 小时前
图像颜色理论与数据挖掘应用的全景解析
人工智能·python·opencv·计算机视觉·数据挖掘·视觉检测·pillow
love530love1 小时前
家用或办公 Windows 电脑玩人工智能开源项目配备核显的必要性(含 NPU 及显卡类型补充)
人工智能·windows·python·开源·电脑
chilavert3182 小时前
关于Python 实现接口安全防护:限流、熔断降级与认证授权的深度实践
python·网络安全