【问题标题】:Regex pattern matching unexpected value正则表达式模式匹配意外值
【发布时间】:2015-06-10 14:17:46
【问题描述】:

我正在使用以下 python 正则表达式代码来分析电子邮件收件人字段中的值:

import re

PATTERN = re.compile(r'''((?:[^(;|,)"']|"[^"]*"|'[^']*')+)''')
list = PATTERN.split(raw)[1::2]

列表应输出每个收件人的姓名和地址,基于“,”或“;”作为分隔符。如果这些值在引号内,它们将被忽略,这是名称的一部分,通常是:“姓氏,名字”

大多数情况下,这很有效,但是在以下情况下,我会遇到意外行为:

"Some Name | Company Name" <name@example.com>

在这种情况下,它在“|”上进行拆分特点。即使当我在正则表达式测试器网站上检查模式时,它也会将名称和地址作为一个整体进行选择。我做错了什么?

示例输入是:

"Some Name | Company Name" <name1@example.com>, "Some Other Name | Company Name" <name2@example.com>, "Last Name, First Name" <name3@example.com>

【问题讨论】:

  • 它不会在任何地方分裂。给我一个输出['"Some Name | Company Name" &lt;name@example.com&gt;']
  • 没错,通常一个字符串中会有多个。我想把他们挑出来。但是,如果我在我的谷歌应用引擎上运行它,它会在 |

标签: python regex


【解决方案1】:

这不是对您的问题的直接回答,而是对您似乎正在解决的问题的直接回答,因此可能仍然有帮助:

为了解析电子邮件,我总是广泛使用 Python 的 email library

在你的情况下,你可以使用这样的东西:

from email.utils import getaddresses
from email import message_from_string

msg = message_from_string(str_with_msg_source)
tos = msg.get_all('to', [])
ccs = msg.get_all('cc', [])
resent_tos = msg.get_all('resent-to', [])
resent_ccs = msg.get_all('resent-cc', [])
all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
for (name, address) in all_recipients:
    # do some postprocessing on name or address if necessary

在我的案例中,这总是可靠地在邮件标题中拆分名称和地址。

【讨论】:

  • 这似乎是一个很好的建议。我正在使用 webhook 来解​​析电子邮件。我也可以从 To-field 中输入字符串值吗?
  • 不确定我是否理解正确。但是如果你问你是否可以将它用于单个字符串,那么是的,当然,例如:email.utils.parseaddr('"Mr Smith | Something" &lt;smith@example.com&gt;') 给你('Mr Smith | Something', 'smith@example.com')
  • 知道了。在这里也找到了基于此的答案:stackoverflow.com/questions/5426789/…
【解决方案2】:

您可以使用更简单的正则表达式来拆分文本。

r'(?<=>)\s*,\s*(?=")'

正则表达式解释

  • \s*,\s* 匹配被零个或多个空格包围的, (\s*)

  • (?&lt;=&gt;) 查看断言后面。检查, 前面是否有&gt;

  • (?=") 前瞻断言。检查, 后面是否跟"

测试

>>> re.split(r'(?<=>)\s*,\s*(?=")', string)
['"Some Name | Company Name" <name1@example.com>', '"Some Other Name | Company Name" <name2@example.com>', '"Last Name, First Name" <name3@example.com>']

更正

  • 案例 1 在上面的示例中,我们使用了单个分隔符 ,。如果您希望基于多个分隔符进行拆分,您可以使用字符类

    r'(?<=>)\s*[,;]\s*(?=")'
    
    • [,;] 字符类,匹配 ,;

  • 案例2如cmets中所说,如果地址部分缺失,我们只需在look后面添加"即可

    示例

    >>> string = '"Some Other Name | Company Name" <name2@example.com>, "Some Name, Nothing", "Last Name, First Name" <name3@example.com>' 
    
    >>> re.split(r'(?<=(?:>|"))\s*[,;]\s*(?=")', string)
    ['"Some Other Name | Company Name" <name2@example.com>', '"Some Name, Nothing"', '"Last Name, First Name" <name3@example.com>']
    

【讨论】:

  • 在这种情况下是的,但有时没有包含名称,只有“name@example.com”没有 。因此,我认为需要拆分所有 , 或 ;引号外
  • @Vincent 也可以。在这种情况下,将后面的外观修改为(?&lt;=(&gt;|"),使其在, 之前查找&gt;"
  • @Vincent 我添加了一个编辑。请参阅案例 2 部分。我希望这就是你所说的
  • 非常感谢您的帮助。最后一个问题:如果它是一个不带引号的电子邮件地址,我应该包含什么来匹配?
  • 所以这将是最后的示例字符串:''"Some Other Name | Company Name" , "Some Name, Nothing", , name5@example.com,“姓,名”'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多