用于从文本中解析名称和电子邮件的正则表达式

时间:2015-11-21 10:22:33

标签: regex linux bash perl sed

这是我到目前为止形成的正则表达式:

/(?:("?(?:.*)"?)\s*)?\s<(.*@.*)>|(?:mailto:(.*@.*))|(.*@.*)/gi

You can check it out at regex101

我试图提取姓名&#39; &安培; &#39;电子邮件&#39;来自以下内容:

John Smith <john.smith@gmail.com>
John Smith <johnsmith@gmail.com>
"John Smith" <johnsmith@gmail.com>
"John" <johnsmith@gmail.com>
John Smith<johnsmith@gmail.com>
<johnsmith@gmail.com>
johnsmith@gmail.com
mailto:johnsmith@gmail.com
"John"<johnsmith@gmail.com>

To: John Smith <john.smith@gmail.com>
From: John Smith <john.smith@gmail.com>
Reply-to: john.smith@gmail.com
Return-path: <john.smith@gmail.com>
Message-id: <john.smith@gmail.com>
References: <john.smith@gmail.com>
Original-recipient: rfc822;john.smith@gmail.com
for john.smith@gmail.com
ESMTPSA id <john.smith@gmail.com>
domain of john.smith@gmail.com
envelope-from=john.smith@gmail.com
(ORCPT john.smith@gmail.com)

从头开始,我觉得我好像几乎那里 - 但有三件事有困难:

  • 从第一个捕获组中删除双引号

  • 处理缺少空格的变体:John Smith<johnsmith@gmail.com>

  • &#39;名称&#39;中的误报后一个块的字段,所以我需要一种排除这些的方法(可能使用前面的::=forid,{ {1}}?)

作为一个完整的正则表达式新手,我会很感激知道如何克服这些问题的人的一点指示。

对于好奇的人,我很遗憾地丢失了我的CardDAV以及所有联系人,所以在真正的Linux方式中,我将通过手动解析我的整个原始MBOX重建电子邮件列表,按大多数排序共同的,从那里开始。

我将使用bash of或perl grep

谢谢你的时间!

2 个答案:

答案 0 :(得分:0)

只是一个建议。可能对你来说更适合在发送电子邮件之前检查&#34;&#34;和&#34;电子邮件&#34;并且在电子邮件&#34;之前提取以处理&#34;来自程序逻辑。像这样:

((?:(?![a-z.]+@[a-z.]+\.[a-z]{2,4})(?:.|\r))+)([a-z.]+@[a-z.]+\.[a-z]{2,4})

((?:(?!regex)(?:.|\r))+)(regex) - 这意味着&#34;与正则表达式不匹配的东西&#34;但相反,这是每个符号,包括从一个到无限次重复的字符返回,并记住这个到第一个反向引用,然后尝试匹配正则表达式并将其放在第二个反向引用中。

编辑: 如果你想处理第一组不存在的情况(只有电子邮件存在),这里是修改版本。

((?:(?![a-z.]+@[a-z.]+\.[a-z]{2,4})(?:.|\r))*)([a-z.]+@[a-z.]+\.[a-z]{2,4})

* instead + 

EDIT2: 根据trincot评论改进。

((?:(?![^><@\s=;]+@[^><@\s=;]+\.[a-z]{2,4})(?:.|\r))*)([^><@\s=;]+@[^><@\s=;]+\.[a-z]{2,4})

答案 1 :(得分:0)

这是另一个可能的正则表达式,为了清晰起见,我将其拆分为三行,但应该在一行上:

\s*(?:.*?[:=;]|ORCPT|for|domain of|ESMTPSA id)?
\s*(?:"?([\w ]*?)[ "<])?
\s*<?([\w.]*?@[\w.]*)>?

第一行消除了前缀,因此是非捕获的。它消除了以:;=或某些特定文字结尾的任何内容。

第二行和第三行分别是名称和电子邮件的两个捕获组。

它正确解析您提供的示例。

请参阅regex fiddle

Perl解决方案

您可以启动此perl在线资讯器:

perl -ne 'while(/.../gi){print "$1|$2\n";}' yourinputfile

这将输出捕获的组1和2,由管道符分隔:

John Smith|john.smith@gmail.com
John Smith|johnsmith@gmail.com
John Smith|johnsmith@gmail.com
John|johnsmith@gmail.com
John Smith|johnsmith@gmail.com
|johnsmith@gmail.com
|johnsmith@gmail.com
|johnsmith@gmail.com
John|johnsmith@gmail.com
John Smith|john.smith@gmail.com
John Smith|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com
|john.smith@gmail.com