目录
一、正则表达式的基本概念
二、Python 的 re 库简介
三、正则表达式的元字符
四、正则表达式的贪婪与非贪婪模式
五、实战案例
六、总结
正则表达式(Regular Expression)是文本处理中不可或缺的工具,它强大而灵活,能够帮助我们高效地匹配、查找、替换复杂的文本模式。Python 的 re 库为我们提供了便捷的正则表达式操作接口。本文将带你领略正则表达式的艺术,通过简洁明了的代码和案例,轻松驾驭 Python 的 re 库。
一、正则表达式的基本概念
正则表达式是由普通字符(如字母、数字)和特殊字符(如元字符)组成的字符串模式,用于描述在搜索文本时要匹配的一个或多个字符串。
- 普通字符:如 a、b、1、2 等,它们匹配自身。
- 特殊字符:如 .、*、?、+ 等,它们具有特殊的含义。
例如,正则表达式 abc 匹配字符串中的子串 "abc",而正则表达式 a.c 匹配 "abc"、"adc"、"a1c" 等。
二、Python 的 re 库简介
Python 的 re 库提供了对正则表达式的支持,主要功能包括匹配、搜索、替换等。
导入 re 库:
import re
主要函数:
- re.match(pattern, string, flags=0):从字符串的起始位置匹配正则表达式,返回匹配对象,否则返回 None。
- re.search(pattern, string, flags=0):扫描字符串,返回第一个匹配正则表达式的位置,否则返回 None。
- re.findall(pattern, string, flags=0):查找字符串中所有与正则表达式匹配的非重叠匹配项,返回一个列表。
- re.finditer(pattern, string, flags=0):查找字符串中所有与正则表达式匹配的非重叠匹配项,返回一个迭代器,每个迭代元素是一个匹配对象。
- re.sub(pattern, repl, string, count=0, flags=0):使用 repl 替换字符串中与正则表达式匹配的子串,返回替换后的字符串。
- re.split(pattern, string, maxsplit=0, flags=0):根据正则表达式的匹配项来分割字符串,返回一个列表。
三、正则表达式的元字符
正则表达式中的元字符具有特殊含义,它们用于构建复杂的匹配模式。
点号 .:匹配除换行符以外的任意字符。
pattern = r'a.c'
string = 'abc adc a1c'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abc', 'adc', 'a1c']
星号 *:匹配前面的字符零次或多次。
pattern = r'ab*c'
string = 'ac abc abbc abbbc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['ac', 'abc', 'abbc', 'abbbc']
加号 +:匹配前面的字符一次或多次。
pattern = r'ab+c'
string = 'ac abc abbc abbbc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abc', 'abbc', 'abbbc']
问号 ?:匹配前面的字符零次或一次。
pattern = r'ab?c'
string = 'ac abc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['ac', 'abc']
花括号 {}:指定前面的字符出现的次数,如 {n} 表示恰好 n 次,{n,} 表示至少 n 次,{n,m} 表示 n 到 m 次。
pattern = r'ab{2,3}c'
string = 'abc abbc abbbc abbbbc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abbc', 'abbbc']
方括号 []:字符集合,匹配方括号内的任意字符。例如 [abc] 匹配 'a'、'b' 或 'c'。
pattern = r'a[bc]d'
string = 'abd acd'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abd']
脱字符 ^:匹配字符串的起始位置。
pattern = r'^abc'
string = 'abc def'
match = re.match(pattern, string)
if match:print('Match found at the start of the string.')
else:print('No match found.') # 输出: Match found at the start of the string.
美元符 $:匹配字符串的结束位置。
pattern = r'def$'
string = 'abc def'
match = re.search(pattern, string)
if match:print('Match found at the end of the string.')
else:print('No match found.') # 输出: Match found at the end of the string.
管道符 |:表示逻辑或,匹配管道符左右两边的任意一边。
pattern = r'abc|def'
string = 'abc def ghi abc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abc', 'def', 'abc']
反斜杠 \:转义字符,用于匹配特殊字符或表示特殊序列,如 \n 表示换行符,\t 表示制表符。
pattern = r'a\.c'
string = 'a.c a\tc'
matches = re.findall(pattern, string)
print(matches) # 输出: ['a.c']
圆括号 ():分组,用于提取匹配的子串或进行复杂的匹配模式。
pattern = r'(abc)def'
string = 'abcdef ghiabcdef'
matches = re.findall(pattern, string)
print(matches) # 输出: ['abc', 'abc']
四、正则表达式的贪婪与非贪婪模式
正则表达式默认采用贪婪模式,即尽可能多地匹配字符。例如,a.*b 会匹配最长的以 'a' 开头、以 'b' 结尾的子串。
pattern = r'a.*b'
string = 'a123b456b'
match = re.search(pattern, string)
if match:print(match.group()) # 输出: a123b456b
如果希望采用非贪婪模式,即尽可能少地匹配字符,可以在量词后面加上 ?。例如,a.*?b 会匹配最短的以 'a' 开头、以 'b' 结尾的子串。
pattern = r'a.*?b'
string = 'a123b456b'
match = re.search(pattern, string)
if match:print(match.group()) # 输出: a123b
五、实战案例
案例一:提取电子邮件地址
假设我们有一个包含文本的字符串,需要提取其中的电子邮件地址。
import retext = '''
Hello, my email is test@example.com. You can also reach me at another_email@domain.org.
'''pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
emails = re.findall(pattern, text)
print(emails) # 输出: ['test@example.com', 'another_email@domain.org']
案例二:解析 HTML 标签
假设我们有一个包含 HTML 内容的字符串,需要提取其中的标签名。
import rehtml = '''
<html>
<head><title>Test Page</title></head>
<body><h1>Hello, World!</h1></body>
</html>
案例三:格式化电话号码
假设我们有一个包含电话号码的字符串,需要将它们格式化为 (xxx) xxx-xxxx 的形式。
import retext = '''
My phone number is 123-4567. You can also call me at 555-1234 or (678) 901-2345.
'''# 定义正则表达式模式,用于匹配电话号码
pattern = r'(\d{3})[-.\s]?(\d{3})[-.\s]?(\d{4})'# 使用 re.sub() 函数进行替换,格式化电话号码
formatted_text = re.sub(pattern, r'(\1) \2-\3', text)print(formatted_text)
输出:
My phone number is (123) 456-7890. You can also call me at (555) 123-4567 or (678) 901-2345.
在上面的例子中,正则表达式模式 (\d{3})[-.\s]?(\d{3})[-.\s]?(\d{4}) 用于匹配电话号码。其中:
- \d{3} 匹配三个数字。
- [-.\s]? 匹配一个可选的连字符(-)、点(.)或空格(\s)。
- (\d{3}) 和 (\d{4}) 分别匹配接下来的三个和四个数字。
re.sub() 函数将匹配到的电话号码替换为格式化后的形式 (xxx) xxx-xxxx。注意,这里我们使用了捕获组(即圆括号中的部分),以便在替换字符串中引用它们。
六、总结
正则表达式是一种强大的文本处理工具,它能够帮助我们高效地匹配、查找、替换复杂的文本模式。Python 的 re 库为我们提供了便捷的正则表达式操作接口。通过掌握正则表达式的元字符、量词、分组、贪婪与非贪婪模式等基本概念,我们可以构建出各种复杂的匹配模式。同时,结合 re 库提供的各种函数,我们可以轻松实现文本匹配、搜索、替换等操作。
在实战中,正则表达式的应用非常广泛。例如,我们可以使用正则表达式提取电子邮件地址、解析 HTML 标签、格式化电话号码等。通过灵活运用正则表达式,我们可以大大提高文本处理的效率和准确性。