Python中的正则表达式(Regular Expression,简称regex)是一种强大的文本处理工具,用于匹配、查找、替换等复杂文本模式。
Python通过re模块提供了对正则表达式的支持。
基础概念
- 字符匹配:
- .:匹配任意单个字符(除换行符)
- \d:匹配数字,等价于[0-9]
- \D:匹配非数字
- \w:匹配字母数字及下划线,等价于[a-zA-Z0-9_]
- \W:匹配非字母数字及下划线
- \s:匹配任意空白字符,如空格、制表符等
- \S:匹配非空白字符
- 量词:
- *:前面的元素出现0次或多次
- +:前面的元素出现1次或多次
- ?:前面的元素出现0次或1次
- {m}:前面的元素恰好出现m次
- {m,n}:前面的元素至少出现m次,最多n次
- 边界匹配:
- ^:匹配字符串开始
- $:匹配字符串结束
- \b:匹配单词边界
- \B:匹配非单词边界
- 组与捕获:
- (pattern):对pattern进行分组并捕获匹配的内容
- (?:pattern):非捕获分组,只进行分组不捕获内容
- 特殊序列:
- \n:换行符
- \t:制表符
- \:匹配反斜杠\
常用函数
- re.search(pattern, string): 在整个字符串中搜索匹配项,不局限于字符串的开始。只要在字符串中的任意位置找到一个匹配项,它就会停止搜索并返回第一个成功的匹配对象。
- re.match(pattern, string): 只在字符串的开始位置尝试匹配模式。如果字符串开始没有匹配到,则返回None,不会继续在字符串中的其他位置查找。
python
result5 = re.match(r'\d+', '123abc') # # 匹配一个或多个数字
print(result5.group()) # 123
result6 = re.match(r'\d+', 'def123abc')
print(type(result6)) # <class 'NoneType'>
result7 = re.search(r'\d+', 'def123abc')
print(result7.group()) #123
- re.findall(pattern, string): 返回字符串中所有与正则表达式匹配的所有非重叠匹配项的列表。
- re.sub(pattern, repl, string): 将字符串中匹配到的部分替换为指定的字符串。
python
text1 = 'Hello, my number is 123-456-7890.'
number = re.search(r'\d{3}-\d{3}-\d{4}', text1)
if number:
print(f'My number is {number.group()}.') # My number is 123-456-7890.
print(type(number)) # <class 're.Match'>
text2 = 'My emails are example@126.com, example@test.cn and example@yahoo.com.cn'
emails = re.findall(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9._-]+\.[A-Za-z]+(?:\.[A-Za-z]{2,})?', text2) # (?:\.[A-Za-z]{2,})? 是为了识别二级域名
# emails = re.findall(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9._-]+\.[A-Za-z]+(?:\.[A-Za-z]+)?', text2)
print(emails) # ['example@126.com', 'example@test.cn', 'example@yahoo.com.cn']
print(type(emails)) # <class 'list'>
text3 = "This is a test, replace the word 'test' with 'example'."
resuilt = re.sub(r'test', 'example', text3) # 返回替换后的文本
print(resuilt) # This is a example, replace the word 'example' with 'example'.
- re.split(pattern, string, maxsplit=0, flags=0):用于根据正则表达式来分割字符串
- pattern: 一个字符串或编译好的正则表达式对象。这个模式定义了用来分割字符串的规则。
- string: 需要被分割的原始字符串。
- maxsplit: 可选参数,指定最大分割次数。默认为0,意味着不限制分割次数,只要满足条件就会一直分割。
- flags: 可选参数,用于指定匹配模式,如忽略大小写、多行模式等。默认为0,即没有特殊匹配模式。
python
text4 = "Hello World! I\'m a robot."
result1 = re.split(r'\W+', text4) # 带+可以一并处理!和空格
print(result1) # ['Hello', 'World', 'I', 'm', 'a', 'robot', ''] 最后那个是空字符串,如果没有最后的标点.则没有这个空字符串
result2 = re.split(r'\W+', text4,maxsplit=2) # 通过设置maxsplit=2,限制了最多分割两次
print(result2) # ['Hello', 'World', "I'm a robot."]
result3 = re.split(r'(\w+)',text4) # 分隔符是字母,由于它被括号包围,所以也会作为结果的一部分被返回
print(result3) # ['', 'Hello', ' ', 'World', '! ', 'I', "'", 'm', ' ', 'a', ' ', 'robot', '.']
- re.finditer 用于在字符串中找到所有匹配正则表达式的子串,并返回一个迭代器,迭代器中包含的是匹配对象。每个匹配对象都包含了匹配到的字符串的信息,比如起始和结束位置等。
python
result4 = re.finditer(r'(\w+)', text4)
print(type(result4)) # <class 'callable_iterator'>
for i in result4:
print(f'\'{i.group()}\' start: {i.start()}, end: {i.end()}, span: {i.span()}.')
# 'Hello' start: 0, end: 5, span: (0, 5).
# 'World' start: 6, end: 11, span: (6, 11).
# 'I' start: 13, end: 14, span: (13, 14).
# 'm' start: 15, end: 16, span: (15, 16).
# 'a' start: 17, end: 18, span: (17, 18).
# 'robot' start: 19, end: 24, span: (19, 24).
- re.subn(pattern, repl, string, count=0, flags=0) 方法与re.sub非常相似,也是用于替换字符串中匹配到的模式。不同之处在于,它返回一个元组(new_string, number_of_subs_made),其中new_string是替换后的新字符串,与re.sub返回的相同,而number_of_subs_made是一个整数,表示实际完成的替换次数。
python
text5 = 'Hello world! Hello Python!'
result8 = re.sub(r'Hello','Hi',text5)
print(result8) # Hi world! Hi Python!
result9 = re.subn(r'Hello','Hi',text5)
print(result9) # ('Hi world! Hi Python!', 2)