正则表达式(python实例)
一、简介
正则表达式(Regular Expressions,简称 Regex)是一种用来描述文本模式的工具,它通过一系列字符和特殊字符组合成的表达式,用于在文本中进行模式匹配和搜索。这些模式可以用来检索、替换、分割字符串,以及验证输入的格式是否符合要求。
python
中,使用正则表达式通常涉及到 re
模块。这个模块提供了一组功能,用于处理正则表达式。
二、正则表达式
基本组成
1. 字符匹配
.
: 匹配除换行符以外的任何单字符。\d
: 匹配一个数字字符。等价于[0-9]
。\D
: 匹配一个非数字字符。等价于[^0-9]
。\w
: 匹配字母、数字、下划线。等价于[a-zA-Z0-9_]
。\W
: 匹配非字母数字下划线。等价于[^a-zA-Z0-9_]
。\s
: 匹配任何空白字符,包括空格、制表符、换行符等。\S
: 匹配任何非空白字符。[]
: 字符集,匹配包含的任一字符。例如[a-z]
匹配任何小写字母。
2. 量词
*
: 匹配前面的子表达式零次或多次。+
: 匹配前面的子表达式一次或多次。?
: 匹配前面的子表达式零次或一次。{n}
: 精确匹配 n 次。{n,}
: 匹配 n 次或更多次。{n,m}
: 匹配 n 到 m 次。
3. 位置和断言
^
: 匹配输入字符串的开始位置。$
: 匹配输入字符串的结束位置。\b
: 匹配一个单词边界。\B
: 匹配非单词边界。(?=...)
: 正前瞻,断言此位置的后面能匹配表达式。(?!...)
: 负前瞻,断言此位置的后面不能匹配表达式。(?<=...)
: 正后顾,断言此位置的前面能匹配表达式。(?<!...)
: 负后顾,断言此位置的前面不能匹配表达式。
4. 分组和引用
()
: 匹配括号内的表达式,也表示一个组。(?P<name>...)
: 匹配的子字符串可以通过名字来引用。\1
,\2
, … : 引用第一、第二等括号内匹配的内容。
5. 特殊字符的转义
- 使用反斜杠
\
来转义特殊字符(如*
,+
,?
,{
,}
,(
,)
等)。
进阶用法
1. 条件表达式(仅限部分实现):
(?(cond)yes-pattern|no-pattern)
根据条件选择匹配模式。
2. 递归模式(非标准,某些实现如 PCRE 提供支持):
- 用于匹配嵌套的结构,如括号嵌套、HTML 标签等。
3. 注释和可读性
- 在正则表达式中使用
#
来添加注释,需要配合re.VERBOSE
或re.X
标志使用。
三、re模块中的方法
1. 基本匹配和搜索
re.match(pattern, string, flags=0)
: 从字符串开头开始匹配。re.search(pattern, string, flags=0)
: 在整个字符串中搜索模式的第一个出现。re.fullmatch(pattern, string, flags=0)
: 要求整个字符串完全匹配正则表达式。
2. 查找和替换
re.sub(pattern, repl, string, count=0, flags=0)
: 替换字符串中的匹配项。re.subn(pattern, repl, string, count=0, flags=0)
: 类似sub
,但返回一个包含新字符串和替换次数的元组。
3. 分割字符串
re.split(pattern, string, maxsplit=0, flags=0)
: 使用模式分割字符串。
4. 编译表达式
re.compile(pattern, flags=0)
: 编译正则表达式,返回一个正则表达式对象,可以重复使用以提高效率。
5. 迭代匹配
re.finditer(pattern, string, flags=0)
: 返回一个迭代器,每次迭代返回一个匹配对象。
6. 提取所有匹配
re.findall(pattern, string, flags=0)
: 返回一个包含所有匹配结果的列表,如果有多个捕获组,则返回元组。
7. 匹配对象方法
MatchObject.group(num=0)
: 返回特定的捕获组。如果num
参数未提供或者为 0,则返回整个匹配的字符串。MatchObject.groups(default=None)
: 返回一个包含所有捕获组的元组。MatchObject.groupdict(default=None)
: 返回一个字典,包含所有命名的捕获组。MatchObject.start(group=0)
,MatchObject.end(group=0)
,MatchObject.span(group=0)
: 获取捕获组的开始、结束位置和范围。MatchObject.expand(template)
: 根据模板展开匹配字符串。
8. 标志
re.I
/re.IGNORECASE
: 忽略大小写。re.M
/re.MULTILINE
: 多行匹配。re.S
/re.DOTALL
: 使.
特殊字符匹配任何字符,包括换行。re.X
/re.VERBOSE
: 允许正则表达式中的空白和注释。re.DEBUG
: 打印关于编译表达式的调试信息。
9. 实用函数
re.escape(pattern)
: 转义字符串中的所有正则特殊字符。re.purge()
: 清除正则表达式缓存。
10. 高级特性
re.Scanner
: 提供一种将字符串分割成符号(token)的方法。
四、实例
1. re.match
re.match(pattern, string, flags=0)
import re# 定义一个正则表达式模式,用来匹配电话号码
pattern = re.compile(r'\d{3}-\d{4}-\d{4}')# 待匹配的字符串
# string = "我的电话号码是:123-4567-8901,你的是:234-5678-9012。" # 这个是不能找到的
string = "123-4567-8901 是我的电话号码。" # 这个是能够匹配到的。# 使用 pattern.match() 进行匹配,match是从头开始进行匹配的。
match = pattern.match(string)if match:print("找到电话号码:", match.group())
else:print("未找到匹配的电话号码。")
2. re.search
re.search(pattern, string, flags=0)
import re# 定义一个正则表达式模式,用来匹配电话号码
pattern = re.compile(r'\d{3}-\d{4}-\d{4}')# 待匹配的字符串
string = "我的电话号码是:123-4567-8901,你的是:234-5678-9012。"# 使用 pattern.search() 进行匹配, 从整个字符串中进行搜索匹配的。
match = pattern.search(string)if match:print("找到电话号码:", match.group())
else:print("未找到匹配的电话号码。")
3. re.fullmatch
re.fullmatch(pattern, string, flags=0)
import re# 定义一个正则表达式模式,用来匹配整个字符串是否为数字
pattern = re.compile(r'\d+')# 待匹配的字符串
string = "123456"# 使用 pattern.fullmatch() 进行匹配, 判断字符串与模式是否完全匹配。
match = pattern.fullmatch(string)if match:print("整个字符串与模式完全匹配。")
else:print("整个字符串与模式不完全匹配。")
4. re.sub
re.sub(pattern, repl, string, count=0, flags=0)
import re# 定义一个正则表达式模式,用来匹配连续的数字
pattern = re.compile(r'\d+')# 待匹配的字符串
string = "今天的日期是2024年5月13日。"# 使用 pattern.sub() 进行替换,将数字替换为 "NUM"
new_string = pattern.sub("NUM", string)print("替换后的字符串:", new_string)
5. re.subn
re.subn(pattern, repl, string, count=0, flags=0)
import re# 定义一个正则表达式模式,用来匹配连续的数字
pattern = re.compile(r'\d+')# 待匹配的字符串
string = "今天的日期是2024年5月13日。"# 使用 pattern.subn() 进行替换,将数字替换为 "NUM"
new_string, count = pattern.subn("NUM", string)print("替换后的字符串:", new_string)
print("替换执行的次数:", count)
6. re.split
re.split(pattern, string, maxsplit=0, flags=0)
import re# 定义一个正则表达式模式,用来匹配空格或逗号作为分隔符
pattern = re.compile(r'[\s,]')# 待分割的字符串
string = "apple, banana, orange, mango"# 使用 pattern.split() 进行分割
result = pattern.split(string)print("分割后的结果:", result)
7. re.compile
re.compile(pattern, flags=0)
import re# 定义一个正则表达式模式,用来匹配包含 "apple" 的单词
pattern = re.compile(r'\bapple\b', flags=re.IGNORECASE)# 待匹配的字符串
string = "I have an Apple and an apple, but no pineapple."# 使用 pattern 进行匹配
matches = pattern.findall(string)print("匹配到的单词:", matches)
8. re.finditer
re.finditer(pattern, string, flags=0)
import re# 定义一个正则表达式模式,用来匹配连续的字母
pattern = re.compile(r'[a-zA-Z]+')# 待匹配的字符串
string = "Hello, World! How are you today?"# 使用 pattern.finditer() 进行匹配
matches = pattern.finditer(string)# 遍历匹配对象,并输出匹配的内容和位置
for match in matches:print("匹配内容:", match.group())print("匹配位置:", match.start(), "-", match.end())
9. re.findall
re.findall(pattern, string, flags=0)
import re# 定义一个正则表达式模式,用来匹配所有连续的数字
pattern = re.compile(r'\d+')# 待匹配的字符串
string = "I have 3 apples, 2 bananas, and 5 oranges."# 使用 pattern.findall() 进行匹配
matches = pattern.findall(string)print("匹配到的数字:", matches)
10. MatchObject.group
MatchObject.group(num=0)
import re# 定义一个正则表达式模式,用来匹配连续的字母
pattern = re.compile(r'[a-zA-Z]+')# 待匹配的字符串
string = "Hello, World!"# 使用 pattern.match() 进行匹配
match = pattern.match(string)# 获取整个匹配的字符串
print("整个匹配的字符串:", match.group())# 获取第一个分组的匹配字符串
print("第一个分组的匹配字符串:", match.group(0))
11. MatchObject.groups
MatchObject.groups(default=None)
import re# 定义一个正则表达式模式,包含两个分组
pattern = re.compile(r'(\d+)-(\w+)')# 待匹配的字符串
string = "2024-May"# 使用 pattern.match() 进行匹配
match = pattern.match(string)# 获取所有捕获分组的匹配字符串
print("所有捕获分组的匹配字符串:", match.groups())# 获取所有捕获分组的匹配字符串,设置默认值为 'N/A'
print("所有捕获分组的匹配字符串(设置默认值):", match.groups(default='N/A'))
12. MatchObject.groupdict
MatchObject.groupdict(default=None)
import re# 定义一个正则表达式模式,包含两个命名分组
pattern = re.compile(r'(?P<year>\d+)-(?P<month>\w+)')# 待匹配的字符串
string = "2024-May"# 使用 pattern.match() 进行匹配
match = pattern.match(string)# 获取命名分组捕获的匹配内容
print("命名分组捕获的匹配内容:", match.groupdict())# 获取命名分组捕获的匹配内容,设置默认值为 'N/A'
print("命名分组捕获的匹配内容(设置默认值):", match.groupdict(default='N/A'))
13. MatchObject.start
MatchObject.start(group=0)
import re# 定义一个正则表达式模式,用来匹配连续的字母
pattern = re.compile(r'[a-zA-Z]+')# 待匹配的字符串
string = "Hello, World!"# 使用 pattern.match() 进行匹配
match = pattern.match(string)# 获取整个匹配的起始位置
print("整个匹配的起始位置:", match.start())# 获取第一个分组的起始位置
print("第一个分组的起始位置:", match.start(0))
14. MatchObject.end
MatchObject.end(group=0)
import re# 定义正则表达式模式
pattern = r'\d+'# 在文本中搜索匹配项
text = "The price is $100 and $200"
match = re.search(pattern, text)# 如果找到匹配项,则获取其结束位置
if match:print("匹配项的结束位置(整个匹配):", match.end())print("匹配项的结束位置(组0):", match.end(0))
15. MatchObject.span
MatchObject.span(group=0)
import re# 定义正则表达式模式
pattern = r'\d+'# 在文本中搜索匹配项
text = "The price is $100 and $200"
match = re.search(pattern, text)# 如果找到匹配项,则获取其起始和结束位置
if match:print("匹配项的起始位置和结束位置(整个匹配):", match.span())print("匹配项的起始位置和结束位置(组0):", match.span(0))
16. MatchObject.expand
MatchObject.expand(template)
import re# 定义一个正则表达式模式,包含两个分组
pattern = re.compile(r'(\d+)-(\w+)')# 待匹配的字符串
string = "2024-May"# 使用 pattern.match() 进行匹配
match = pattern.match(string)# 定义一个模板字符串,使用 \1 和 \2 表示第一个和第二个捕获分组
template = r"Year: \1, Month: \2"# 将模板应用到匹配的结果上
result = match.expand(template)print("扩展后的结果:", result)
17. re.IGNORECASE
import re# 在字符串中查找"hello",不区分大小写
pattern = re.compile(r'hello', re.IGNORECASE)
result = pattern.search("HeLLo, World!")
if result:print("找到匹配项:", result.group())
else:print("未找到匹配项")
18. re.MULTILINE
import re# 在多行文本中查找以"start"开头、以"end"结尾的内容
pattern = re.compile(r'^start.*end$', re.MULTILINE)
text = """start line one end
start line two end
start line three end"""matches = pattern.findall(text)print("找到的匹配项:")
for match in matches:print(match)
19. re.DOTALL
import re# 定义正则表达式模式,匹配任意字符
pattern = r'Hello.+World'# 在文本中搜索匹配项
text = "Hello\nWorld"
match = re.search(pattern, text)
if match:print("默认情况下,不匹配换行符:")print(match.group())# 使用re.DOTALL标志,使`.`匹配包括换行符在内的任意字符
pattern_dotall = r'Hello.+World'
match_dotall = re.search(pattern_dotall, text, flags=re.DOTALL)
if match_dotall:print("使用re.DOTALL标志,匹配包括换行符在内的任意字符:")print(match_dotall.group())
20. re.VERBOSE
import re# 匹配一个简单的电子邮件地址
pattern = re.compile(r'''^ # 匹配字符串的开始[\w\.-]+ # 匹配用户名部分@ # 匹配 @ 符号[\w\.-]+ # 匹配域名部分\. # 匹配点号[a-zA-Z]{2,} # 匹配顶级域名$ # 匹配字符串的结束
''', re.VERBOSE)email = "example@email.com"if pattern.match(email):print("这是一个有效的电子邮件地址。")
else:print("这不是一个有效的电子邮件地址。")
21. re.DEBUG
import re# 编译正则表达式并输出调试信息
pattern = re.compile(r'^start.*end$', re.DEBUG)
22. re.escape
re.escape(pattern)
import re# 定义一个包含特殊字符的模式
pattern_with_special_chars = ".*$^"# 使用re.escape()函数转义模式中的特殊字符
escaped_pattern = re.escape(pattern_with_special_chars)# 输出转义后的模式
print("转义后的模式:", escaped_pattern)# 在文本中搜索转义后的模式
text = "The pattern is .* and it matches the end of the line $"
match = re.search(escaped_pattern, text)if match:print("找到匹配项:", match.group())
else:print("未找到匹配项")
23. re.purge
import re# 编译一些正则表达式模式并存储在缓存中
pattern1 = re.compile(r'\d+')
pattern2 = re.compile(r'[a-zA-Z]+')
pattern3 = re.compile(r'\W+')# 清除正则表达式缓存
re.purge()# 此时缓存已被清空,再次使用这些模式时将重新编译
24. re.Scanner
import re# 定义扫描器模式,格式为 (正则表达式, 处理函数)
scanner = re.Scanner([(r'\d+', lambda scanner, token: ("NUMBER", int(token))),(r'[a-zA-Z]+', lambda scanner, token: ("WORD", token)),(r'\s+', lambda scanner, token: None), # 忽略空白字符
])# 要扫描的字符串
text = "The 42 quick brown foxes"# 使用扫描器对字符串进行分割
tokens, remainder = scanner.scan(text)# 输出分割后的结果
print("Tokens:", tokens)
print("Remainder:", remainder)