
题目考点
这道题主要考:
email.utils.parseaddr()解析姓名和邮箱地址- 正则表达式
re判断字符串格式 - 循环读取多行输入
- 按条件筛选并输出原格式数据
这道题不是让你手动切字符串,而是希望你用 email.utils 把:
DEXTER <dexter@hotmail.com>
解析成:
('DEXTER', 'dexter@hotmail.com')
然后只检查后面的邮箱地址是否合法。
审题
题目给你 n 行,每一行格式大致是:
name <username@domain.extension>
要求你只打印邮箱合法的那几行,并且输出顺序要和输入顺序一致。
合法邮箱要满足:
username@domain.extension
其中:
| 部分 | 要求 |
|---|---|
| username | 第一个字符必须是英文字母 |
| username 后续字符 | 可以是字母、数字、_、-、. |
| domain | 只能是英文字母 |
| extension | 只能是英文字母,长度为 1 到 3 |
样例中:
DEXTER <dexter@hotmail.com>
是合法的。
而:
VIRUS <virus!@variable.:p>
不合法,因为 virus! 里面有 !,并且扩展名 :p 也不符合要求。
思路提示
先不要急着写正则。你可以按下面三步想:
第一步,先用 email.utils.parseaddr() 把一整行拆开。
例如:
DEXTER <dexter@hotmail.com>
可以拆成:
name = "DEXTER"
address = "dexter@hotmail.com"
第二步,只判断 address 这一部分是否合法。
也就是说,我们要判断:
dexter@hotmail.com
是不是满足:
用户名@域名.扩展名
第三步,如果合法,就用 email.utils.formataddr() 再拼回标准格式并输出。
完整设计思路
第一步:读取输入行数
题目第一行是整数 n,表示后面有多少组姓名和邮箱。
n = int(input())
第二步:逐行读取姓名和邮箱
用循环读取 n 行:
for _ in range(n):
line = input()
这里 _ 表示这个循环变量本身不重要,只是重复执行 n 次。
第三步:解析姓名和邮箱
用:
name, address = email.utils.parseaddr(line)
例如:
DEXTER <dexter@hotmail.com>
会得到:
name = "DEXTER"
address = "dexter@hotmail.com"
第四步:用正则判断邮箱地址
核心正则可以写成:
r'[A-Za-z][A-Za-z0-9_.-]*@[A-Za-z]+\.[A-Za-z]{1,3}'
拆开看:
| 正则片段 | 含义 |
|---|---|
[A-Za-z] | 用户名第一个字符必须是英文字母 |
[A-Za-z0-9_.-]* | 后续字符可以是字母、数字、下划线、点、横线,出现 0 次或多次 |
@ | 必须有一个 @ |
[A-Za-z]+ | 域名只能由英文字母组成,至少 1 个 |
\. | 必须有一个真正的点号 . |
[A-Za-z]{1,3} | 扩展名只能是英文字母,长度 1 到 3 |
注意这里的:
\.
表示真正的点号。
如果直接写:
.
在正则里它表示“任意一个字符”,不是普通点号。
代码实现
import re
import email.utils
n = int(input())
pattern = r'[A-Za-z][A-Za-z0-9_.-]*@[A-Za-z]+\.[A-Za-z]{1,3}'
for _ in range(n):
line = input()
name, address = email.utils.parseaddr(line)
if re.fullmatch(pattern, address):
print(email.utils.formataddr((name, address)))
这里推荐用:
re.fullmatch(pattern, address)
它表示整个 address 必须完整匹配这个正则规则。
如果只用 re.match(),它默认是从开头开始匹配,但不一定要求整个字符串都匹配完。初学阶段用 fullmatch() 更直观。
运行演示
输入:
2
DEXTER <dexter@hotmail.com>
VIRUS <virus!@variable.:p>
程序先读到:
n = 2
第一行:
DEXTER <dexter@hotmail.com>
经过:
email.utils.parseaddr(line)
得到:
name = "DEXTER"
address = "dexter@hotmail.com"
然后判断:
dexter@hotmail.com
拆开看:
dexter -> 用户名,d 开头是字母,后面都是合法字符
hotmail -> 域名,全是字母
com -> 扩展名,全是字母,长度是 3
所以合法,输出:
DEXTER <dexter@hotmail.com>
第二行:
VIRUS <virus!@variable.:p>
解析后:
name = "VIRUS"
address = "virus!@variable.:p"
判断邮箱:
virus! -> 用户名里面有 !,不合法
:p -> 扩展名也不合法
所以这一行不输出。
最终输出:
DEXTER <dexter@hotmail.com>
方法总结
这类题的核心不是一上来写代码,而是先拆格式。
以后遇到“判断字符串是否合法”的题,可以按这个顺序思考:
第一步,先明确字符串整体格式。
比如这题是:
username@domain.extension
第二步,把格式拆成几段。
比如:
username
@
domain
.
extension
第三步,分别给每一段写规则。
比如:
username 第一个字符必须是字母
domain 只能是字母
extension 长度 1 到 3
第四步,把这些规则拼成一个完整正则。
这道题的关键正则是:
r'[A-Za-z][A-Za-z0-9_.-]*@[A-Za-z]+\.[A-Za-z]{1,3}'
你不需要一口气背下来,而是要学会从题目条件一步一步拼出来。
练习
请判断下面哪些邮箱地址合法:
ALEX <alex-99@gmail.com>
BOB <1bob@yahoo.com>
CAT <cat.name@abc.cn>
DOG <dog@hello.python>
EVA <eva_2024@school.edu>
提示:
重点检查三件事:
- 用户名第一个字符是不是英文字母
domain是不是只包含英文字母extension长度是不是 1 到 3,并且只包含英文字母



