输入(以逗号分隔的列表):
"\"Mr ABC\" <mr@abc.com>, \"Foo, Bar\" <foo@bar.com>, mr@xyz.com"
预期输出(2元组列表):
[("Mr ABC", "mr@abc.com"), ("Foo, Bar", "foo@bar.com"), ("", "mr@xyz.com")]
我实际上可以使用逗号分割,然后使用email.utils.parseaddr(address)
,直到我意识到名称部分也可以包含逗号,就像上面的“Foo,Bar”一样。
email.utils.getaddresses(fieldvalues)
非常接近我的需要,但它接受一个序列,而不是逗号分隔的字符串。
答案 0 :(得分:3)
您可以使用以下
import re
p = re.compile(r'"([^"]+)"(?:\s+<([^<>]+)>)?')
test_str = '"Mr ABC" <mr@abc.com>, "Foo, Bar" <foo@bar.com>, "mr@xyz.com"'
print(re.findall(p, test_str))
输出:[('Mr ABC', 'mr@abc.com'), ('Foo, Bar', 'foo@bar.com'), ('mr@xyz.com', '')]
请参阅IDEONE demo
正则表达式匹配......
"
- 双引号([^"]+)
- (第1组)除双引号外的1个或多个字符"
- 双引号然后,使用(?:...)?
构造引入了一个可选的非捕获组:(?:\s+<([^<>]+)>)?
。它匹配......
\s+
- 一个或多个空白字符<
- 开放角括号([^<>]+)
- (第2组)开启或关闭尖括号以外的1个或多个字符>
- 结束角括号 re.findall
函数将所有捕获组都放入元组列表中:
如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。
<强>更新强>:
如果您需要确保电子邮件是元组中的 second 元素,请使用此代码(请参阅demo):
lst = re.findall(p, test_str)
print([(tpl[1], tpl[0]) if not tpl[1] else tpl for tpl in lst])
# => [('Mr ABC', 'mr@abc.com'), ('Foo, Bar', 'foo@bar.com'), ('', 'mr@xyz.com')]