什么是正则表达式?
正则表达式(Regular Expression)是一种强大的文本处理工具,它使用特定模式来描述、匹配和操作字符串。Python通过内置的re
模块提供正则表达式支持。
为什么使用正则表达式?
- 强大的文本搜索与匹配能力
- 高效验证数据格式(邮箱、电话、URL等)
- 复杂文本的查找与替换
- 快速从文本中提取特定信息
- 文本分割与重组
正则表达式基础语法
字符 | 描述 | 示例 |
---|---|---|
. |
匹配任意单个字符(换行符除外) | a.c 匹配 "abc"、"a@c" |
\d |
匹配任意数字 | \d\d 匹配 "42"、"01" |
\w |
匹配字母、数字或下划线 | \w+ 匹配 "hello"、"var123" |
\s |
匹配空白字符(空格、制表符等) | \s+ 匹配一个或多个空白字符 |
[abc] |
匹配方括号中的任意一个字符 | [aeiou] 匹配任意元音字母 |
[^abc] |
匹配不在方括号中的任意字符 | [^0-9] 匹配非数字字符 |
* |
匹配前面的子表达式零次或多次 | bo*b 匹配 "bb"、"bob" |
+ |
匹配前面的子表达式一次或多次 | bo+b 匹配 "bob"、"boob" |
? |
匹配前面的子表达式零次或一次 | colou?r 匹配 "color"、"colour" |
{n} |
精确匹配n次 | \d{4} 匹配四位数字 |
{n, m} |
匹配至少n次,最多m次 | \d{2,4} 匹配2到4位数字 |
Python re模块核心函数
re.match()
从字符串起始位置匹配模式。如果匹配成功,返回匹配对象;否则返回None。
import re result = re.match(r'Hello', 'Hello, world!') if result: print("匹配成功:", result.group())
re.search()
扫描整个字符串,返回第一个成功的匹配。
import re result = re.search(r'\d{3}', '电话: 123-456-7890') print("找到的数字:", result.group()) # 输出: 123
re.findall()
返回字符串中所有匹配模式的非重叠子串列表。
import re emails = re.findall(r'[\w\.-]+@[\w\.-]+', '联系: email@example.com 或 support@domain.com') print("所有邮箱:", emails)
re.sub()
替换字符串中匹配正则表达式的部分。
import re text = "今天是2023-08-11" new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\1年\2月\3日', text) print(new_text) # 输出: 今天是2023年08月11日
实用案例与技巧
案例1:提取URL中的域名
import re url = "https://www.example.com/path/to/page?query=string" pattern = r'https?://([\w\.-]+)/' match = re.search(pattern, url) if match: print("域名:", match.group(1)) # 输出: www.example.com
案例2:验证邮箱格式
import re def validate_email(email): pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$' return re.match(pattern, email) is not None print(validate_email("user@example.com")) # True print(validate_email("invalid.email@")) # False
案例3:提取HTML标签内容
import re html = "" pattern = r'标题
段落内容
(.*?)
' match = re.search(pattern, html) if match: print("段落内容:", match.group(1)) # 输出: 段落内容
技巧:使用编译后的正则表达式
对于需要多次使用的正则表达式,使用re.compile()
预编译可以提高效率。
import re # 预编译正则表达式 phone_pattern = re.compile(r'(\d{3})-(\d{3})-(\d{4})') text = "电话1: 123-456-7890, 电话2: 098-765-4321" # 使用编译后的模式对象 matches = phone_pattern.findall(text) for match in matches: print(f"区号: {match[0]}, 号码: {match[1]}-{match[2]}")
最佳实践提示
- 使用原始字符串(r'pattern')避免转义字符问题
- 复杂的正则表达式添加注释(使用re.VERBOSE)
- 优先使用非贪婪匹配(*?、+?)避免过度匹配
- 测试正则表达式时使用在线工具(如regex101.com)
- 考虑使用命名分组提高可读性:(?P
...) - 处理用户输入的正则表达式时要格外小心(防止ReDoS攻击)
发表评论