大家好!在处理文本数据时,你是否曾遇到过这样的场景:
- 想从一个网页源码里,把所有的邮箱地址都提取出来。
- 想验证用户输入的是不是一个合法的手机号。
- 想把一段话里所有的数字都替换成星号
*。
如果手动去做这些事,会非常繁琐和低效。今天,我们就来认识一个能帮你解决这些问题的"神器"------正则表达式(Regular Expression)。
什么是正则表达式?
别被这个名字吓到。你可以把它想象成一种描述文本模式的"语法"。
就像我们用 * 号在文件搜索里代表"任意多个字符"一样,正则表达式也有一套自己的特殊符号,用来定义一个"模式"(Pattern)。然后,我们可以用这个"模式"去匹配、查找、替换符合规则的文本。
它就像一个为文本定制的"搜索引擎",强大到超乎想象。
为什么要学正则表达式?
因为它无处不在,而且极其高效:
- 数据清洗:从杂乱的日志、评论中提取有效信息。
- 数据验证:检查用户输入的邮箱、身份证号、URL是否格式正确。
- 文本替换:批量修改或隐藏文本中的特定内容(如手机号)。
- 网络爬虫:精准地从HTML代码中抓取所需数据。
学会它,你的Python文本处理能力将提升一个档次!
Python中的re模块
在Python中,使用正则表达式需要导入 re 模块。它提供了所有我们需要的函数。我们先来认识几个最核心的:
re.search(pattern, string): 扫描整个字符串,找到第一个 匹配pattern的位置,并返回一个"匹配对象"。如果找不到,返回None。re.match(pattern, string): 从字符串的开头 开始匹配。如果开头不符合pattern,就直接失败。re.findall(pattern, string): 扫描整个字符串,找到所有 匹配pattern的子串,并以列表的形式返回。re.sub(pattern, repl, string): 查找并替换。将字符串中所有匹配pattern的子串,替换成repl。
看不懂?没关系,我们结合例子马上就懂了。
正则表达式的"语法元素"(元字符)
这是正则表达式的核心。记住下面这些特殊符号,你就掌握了半壁江山。
| 符号 | 名称 | 解释与例子 |
|---|---|---|
. |
点号 | 匹配任意单个字符 (除了换行符)。a.c 可以匹配 "abc", "a_c", "a5c" 等。 |
* |
星号 | 匹配前面的元素0次或多次 。ab*c 可以匹配 "ac", "abc", "abbc", "abbbbc" 等。 |
+ |
加号 | 匹配前面的元素1次或多次 。ab+c 可以匹配 "abc", "abbc",但不能匹配 "ac"。 |
? |
问号 | 匹配前面的元素0次或1次 。colou?r 可以匹配 "color" 和 "colour"。 |
[] |
方括号 | 匹配方括号中的任意一个 字符。[aeiou] 可以匹配任何一个元音字母。[0-9] 匹配任何一个数字。 |
^ |
脱字符 | 匹配字符串的开头 。^Hello 只能匹配以 "Hello" 开头的字符串。 |
$ |
美元符 | 匹配字符串的结尾 。world$ 只能匹配以 "world" 结尾的字符串。 |
| ` | ` | 竖线 |
() |
圆括号 | 分组 。将括号内的部分作为一个整体。(ab)+ 可以匹配 "ab", "abab", "ababab" 等。 |
\ |
反斜杠 | 转义 。如果你想匹配一个真正的点号 .,你需要写成 \.。 |
特殊序列(快捷方式)
为了方便,正则表达式还提供了一些预定义的字符集:
\d: 匹配任意一个数字 。等价于[0-9]。\w: 匹配任意一个字母、数字或下划线 。等价于[a-zA-Z0-9_]。\s: 匹配任意一个空白字符(空格、制表符、换行符等)。\D,\W,\S: 分别与上面相反,匹配非数字 、非字母数字下划线 、非空白字符。
实战演练:让我们动起手来!
光说不练假把式,我们来看几个真实的例子。
例子1:验证一个简单的手机号
假设我们要验证一个11位的手机号,规则是:以1开头,后面跟10个数字。
python
import re
phone_number1 = "13812345678"
phone_number2 = "12345678901" # 不是以1开头
phone_number3 = "1381234abcd" # 包含非数字
# 定义我们的"模式"
# ^1 : 必须以1开头
# \d{10}: 后面必须跟着10个数字 (\d是数字, {10}表示重复10次)
# $ : 到字符串结尾
pattern = r"^1\d{10}$"
# 使用 re.match() 因为它要求从开头匹配到结尾
if re.match(pattern, phone_number1):
print(f"'{phone_number1}' 是一个有效的手机号。")
else:
print(f"'{phone_number1}' 不是一个有效的手机号。")
if re.match(pattern, phone_number2):
print(f"'{phone_number2}' 是一个有效的手机号。")
else:
print(f"'{phone_number2}' 不是一个有效的手机号。")
输出:
'13812345678' 是一个有效的手机号。
'12345678901' 不是一个有效的手机号。
看到了吗?re.match 完美地完成了我们的验证任务!
例子2:从一段文本中提取所有邮箱
这是一个更常见的场景。我们用 re.findall。
python
import re
text = """
请联系我们:
技术支持: support@example.com
销售咨询: sales@my-company.co.uk
无效邮箱: a@b
另一个联系方式: info@test.org
"""
# 邮箱的模式比较复杂,我们先用一个简化的版本
# [\w.-]+ : 匹配用户名部分,可以包含字母、数字、下划线、点、减号
# @ : 匹配 @ 符号
# [\w.-]+ : 匹配域名部分
# \. : 匹配点号 .
# [a-zA-Z]{2,}: 匹配顶级域名,如 com, net, uk 等,至少2个字母
email_pattern = r"[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}"
emails = re.findall(email_pattern, text)
print("找到的邮箱地址有:")
for email in emails:
print(email)
输出:
找到的邮箱地址有:
support@example.com
sales@my-company.co.uk
info@test.org
re.findall 轻松地把所有符合模式的邮箱都抓出来了!
例子3:替换敏感词
假设我们要把一段话里的所有数字都换成 *。
python
import re
text = "我的电话是 13812345678,我的邮编是 100000。"
# \d+ 匹配一个或多个连续的数字
pattern = r"\d+"
# 使用 re.sub() 进行替换
new_text = re.sub(pattern, "******", text)
print("原文:", text)
print("替换后:", new_text)
输出:
原文: 我的电话是 13812345678,我的邮编是 100000。
替换后: 我的电话是 ******,我的邮编是 ******。
是不是非常方便?
总结
正则表达式初看起来像一堆乱码,但一旦你掌握了它的基本语法,就会发现它处理文本的强大能力。
给新手的建议:
- 不要贪多求全 :先掌握
.*+?[]\d\w^$这些最常用的。 - 动手实践:找一些实际问题,比如验证自己的学号、提取网页内容,去尝试用正则表达式解决。
- 使用在线工具 :像 regex101.com 这样的网站,可以让你实时测试你的正则表达式,并对其进行详细解释,是学习和调试的绝佳帮手。
希望这篇入门博客能为你打开正则表达式的大门。它可能不是最容易掌握的技能,但绝对是你编程工具箱里最锋利的那一把"瑞士军刀"!