如何使用 awk 或 grep 从标题中提取电子邮件字段

Posted

技术标签:

【中文标题】如何使用 awk 或 grep 从标题中提取电子邮件字段【英文标题】:How to extract email fields from headers with awk or grep 【发布时间】:2015-10-12 16:02:17 【问题描述】:

关于:邮箱(mbox格式)电子邮件

多消息文件: Inbox.mbox

From - Thu Mar 26 16:16:21 2015
From: Mail Delivery System <Mailer-Daemon@200.netwizz.com>
To: edge@notterribe.org
Subject: Mail delivery failed: returning message to sender
Message-Id: <E1Yb3yX-0004CB-QH@200.netwizz.com>
Date: Thu, 26 Mar 2015 02:21:17 -0700
Date: Thu, 26 Mar 2015 02:20:44 -0700
From: edge <edge@notterribe.org>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.5.0
MIME-Version: 1.0
To: leasing@theedgehenderson.com
CC: etpmgr@movein.net, t.simmonds@movein.ne
Subject: Fwd: Today's Breach Of Our Security.
From - Fri Mar 27 12:00:00 2015  

所需的模式匹配顺序;

Date: Thu, 26 Mar 2015 02:21:17 -0700  
From - Thu Mar 26 16:16:21 2015  
From: Mail Delivery System <Mailer-Daemon@200.netwizz.com>  
To: edge@notterribe.org  
Message-Id: &lt;E1Yb3yX-0004CB-QH@200.netwizz.com>  
Subject: Mail delivery failed: returning message to sender 

期望的最终结果;

Date: Thu; 26 Mar 2015 02:21:17 -0700;From - Thu Mar 26 16:16:21 2015;From: Mail Delivery System <Mailer-Daemon@200.netwizz.com>;To: edge@notterribe.org;Message-Id: &lt;E1Yb3yX-0004CB-QH@200.netwizz.com>;Subject: Mail delivery failed: returning message to sender

目标; * “Inbox.mbox”中的每封邮件都以“From”开头 * 仅匹配“^Date: |^From |^From: |^To: |^Message-Id: |^Subject:”的第一次出现,打印该行。 * 以分号分隔的csv格式输出结果

我试过了;grep -a -E -i "^Date: |^From |^From: |^To: |^Message-ID: |^Subject: " Inbox.mbox awk '/^Date: / || /^From / || /^From: / || /^To: / || /^Message-ID: / || /^Subject: /' Inbox.mbox

评论:以上内容给了我一个良好的开端,我对 awk 和 grep 最熟悉,所以我只尝试使用它们。难以按我希望的顺序打印出行,匹配第一次出现仅以换行符结尾。一些消息中存在二进制数据,所以我使用 -a 和 grep。

任何帮助将不胜感激。 谢谢。

【问题讨论】:

与:$awk '/^From / head=1; $1 = ""; from = $0 /^From: / head=1; $1 = ""; from2 = $0 /^To: / head=1; $1 = ""; to = $0 /^Date:/ head=1; $1 = ""; date = $0 /^Subject:/ head=1; $1 = ""; subject = $0 /^Message-ID: / head=1; $1 = ""; message = $0 NF == 0 &amp;&amp; head == 1 head=0; print from"\t", from2"\t", to"\t", date"\t", subject"\t", message ' Inbox.mbox更接近 我建议你用另一个库而不是纯shell(比如Python),RFC5322 解析特别棘手,更不用说有很多不同的mbox 格式。跨度> 卡壳。我很确定 Mozilla Thunderbird mbox 邮件文件的每条记录都以“From”开头,并以 2 个空行结尾。 awk '/^From /,/^"\n""\n"^From / print $0' Inbox.mbox 【参考方案1】:

好的,所以你只有 Thunderbird mbox。

这是我的想法,在一个名为 mbox2csv 的文件中:

#!/usr/bin/gawk -f
BEGIN 
    # initialize an array and set the "i" variable to 0
    i = split("", row, ":");


# awk does not have a "join"
function join(array, sep) 
    sep = sep ? sep : ";";
    result = array[0];
    for (i=1; i<length(array); ++i) 
        result = result sep array[i];
    
    return result;


# the keys you want to store
/^(From|Date|To|Message-ID|Subject):/ 
    row[i++] = $0;


# every time we match a mbox message separator
/^From /
    # if there is data (not the first line)
    if (length(row) > 1) 
        print join(row);
        # reinitialise the array and "i"
        i = split("", row, ":");
    

然后:mbox2csv INBOX &gt; result.csv

严重警告:* 这不考虑互联网标题中常见的行延续,也不考虑转义行。

编辑:代码将在gist

【讨论】:

感谢您的解决方案。错误消息...我有 awk 而不是 gawk,我可以将 /usr/bin/gawk -f 更改为 /usr/bin/awk -f 吗?,将您的代码剪切并粘贴到 mbox2csv,chmod a+x mbox2csv。在终端: $ ./mbox2csv Inbox.mbox > result.csv 。失败并出现错误:awk: ./mbox2csv: line 11: illegal reference to local array array&lt;br/&gt; awk: ./mbox2csv: line 25: illegal reference to array row 哪个awk 版本? nawk? bwkawk? mawk? 我的立场是正确的,它是 'mawk' mawk 1.3.3 Nov 1996。哇,这太旧了。是否建议使用更现代的 awk 版本?谢谢。 $ 定位 awk | grep /bin ... 显示 /usr/bin/awk /usr/bin/gawk - 令人困惑。 /usr/bin/igawk /usr/bin/mawk /usr/bin/nawk cmets 编辑超时。 $ dpkg -i "awk" 显示系统上唯一的版本是:mawk 1.3.3-17 amd64 我找不到 mawk 2010-12-10b 之前的版本;您可以测试code from the gist,但我怀疑它是否适用于这么旧的版本。您可以尝试编译最新版本或找到 awk 解释器的独立版本。

以上是关于如何使用 awk 或 grep 从标题中提取电子邮件字段的主要内容,如果未能解决你的问题,请参考以下文章

如何 grep/perl/awk 重叠正则表达式

awk grep 或 sed:如何匹配两个文件

从 Outlook 电子邮件中提取嵌入的图像

从不同文件中查找相关文本并使用 sed 或 awk 或 grep 进行更新

如何使用 grep 或 awk 打印出特定的块? [复制]

Centos7 ,使用grep,cut awk 提取IP地址