【问题标题】:Parse email header from text using PCRE regular expression使用 PCRE 正则表达式从文本中解析电子邮件标题
【发布时间】:2013-10-29 11:40:39
【问题描述】:

我需要解析(拆分)一个包含从 Outlook 导出的电子邮件的文本文件。 我使用preg_splitPREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE 拆分它

我的目标是使用正则表达式捕获邮件标题部分,即从“发件人:”行开始,以邮件正文前的空行结束。

约束:

  • 需要多语言字段名称
  • 标头字段的数量不同(CC、BCC、附件)
  • 某些字段可能不止一行(收件人、抄送、密件抄送、主题、附件)

文本文件经过预处理:用单个空格替换多个空格和制表符,替换前导和尾随空格。

我一整天都在做,无法让最后一部分工作。它确实适用于 [gskinner 正则表达式测试页面]:http://regexr.com?36v27,但不适用于 php。

主题:

From: Black, Jack (LA)
Sent: Monday, October 28, 2013 6:36 PM
To: George, Jackson (London); DCS.CC.DARWIN (Australia)
Cc: Bar, Foo (Istanbul); Ex, Reg (Istanbul); Smith, John (Istanbul); Rambo,
John J. (Gaziantep); Matrix, John (Phuket)
Subject: RE: PREVENTIVE AND CORRECTIVE ACTIONS / FOOBAR

Dear George,

venenatis imperdiet quam. Proin a egestas nunc, et mattis elit. In hac habitasse platea dictumst. Nulla dolor nibh, tempus ut neque eu, tempus fermentum mauris. Mauris nec ipsum nec sapien commodo scelerisque ut eu urna. Pellentesque eu neque in enim adipiscing faucibus. Sed interdum arcu et sem mollis iaculis. Duis euismod laoreet ligula lacinia dapibus. Vestibulum ullamcorper malesuada metus at malesuada. 

 Nullam enim elit, auctor vehicula orci eget, imperdiet feugiat odio. Etiam dapibus sagittis sem a varius. Nulla sit amet convallis mi, sit amet rutrum ipsum. In libero lectus, mattis at dui eu.

Thank you and best regards,

Jack B. Black (Mr)
Operations Manager (GGD)
FU Supervisor (R34, R57)

Phone: +1112212212 (local 1111)
Mobile: +12 121.111.11.12

From: George, Jackson (UK)
Sent: Monday, October 28, 2013 5:57 PM
To: DCS.CC.DARWIN (Australia)
Bar, Foo (Istanbul); Ex, Reg (Istanbul); Smith, John (Istanbul); Rambo,
John J. (Gaziantep); Matrix, John (Phuket)
Subject: PREVENTIVE AND CORRECTIVE ACTIONS / FOOBAR

Dear Colleagues,

ermentum. Duis ipsum quam, bibendum a risus nec, tincidunt fringilla lectus. Nunc vel dictum massa, et cursus nunc. Mauris tincidunt felis eget justo congue volutpat. Nulla condimentum accumsan elementum. Integer commodo, lorem eu pharetra suscipit, ligula.

Best Regards.

SDFD srfgGD
Field coordinator (GGD)
Customer Representative

sds dfsd sdfgsef sdfsd
sgzdfgdfg fgfg gdfg
Footer text etc
sdfdfdf dfgsdfgsdfgsdfg
Phone : +90 212 368 40 00 (ext:3814)

正则表达式:

preg_match(
                 '/                         # delimiter
                (                           # capturing group start
                [\ A-Z][a-z]+:.+\(.+\)\R    # From: field
                [A-Z][a-z]+:.+\R            # Sent: fields
                [A-Z][a-z]+:.+\R            # To: field (1st line)
                (?:.+\R)+              # any additional header lines, before blank line (To, CC, BCC, Subject, Attachments)
                )                           # capturing group end
                # delimiter + modifiers /x',$text_clean, $matches);
        echo '<b>Matches: '.count($matches).'</b>';
        print_r($matches);   

我在获取额外的标题行时遇到问题:

(?:.+\R)+              # any additional header lines...

感谢任何帮助

【问题讨论】:

  • 它对我来说很好用:ideone.com/Xj6aaF。我使用 PHP 的 heredoc syntax 来指定测试字符串。我猜你在 PHP 中指定测试字符串(或导入实际的电子邮件文本)时做错了。发布那个部分,也许有人可以帮助你!
  • 你不能把注释和结束分隔符放在它后面的同一行。
  • 如果 Outlook 像这样导出 Cc: 标头,在字段值的中间有一个无人看管的换行,你基本上就完蛋了。
  • @CasimiretHippolyte 显然,你可以 - 它可以正常工作

标签: php regex preg-match preg-split


【解决方案1】:

最短的方法是使用带有惰性量词的 preg_match_all:

preg_match_all('/^From.*?\R\R/ims', $mails, $matches);
print_r($matches);

【讨论】:

  • 谢谢,但这不行 - 它会匹配消息中间的“发件人”,直到出现空白行。我说过需要多语言字段名称,因此“From”可以是“От”、“Da”等。Outlook(Windows?)翻译成的任何 klanguage。
【解决方案2】:

感谢大家的意见,但是我用我的方法想通了。 有几点让我感到困惑,但工作解决方案在下面。

  1. 为什么preg_match 返回第一个结果两次而不是两次匹配:(http://www.ideone.com/Xj6aaF)1

  2. (?:.+\R)+ 点似乎匹配任何字符且没有字符,这就是为什么它总是缺少空行。我发现这很奇怪 - + 不应该是 1 or more quantifier 吗?

无论如何,当我将正则表达式模式更改为 (?:\S.+\R)+ 时,它会使用 preg_split 完成我想要的操作。

Demo

虽然,从技术上讲,我的问题已经解决了,但我希望有人能解释以上两点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2016-02-23
    相关资源
    最近更新 更多