如何从文件中提取多行扩展的电子邮件标题

时间:2019-02-01 14:55:26

标签: linux email awk sed grep

我正在尝试在Linux上使用sed从电子邮件文件中提取To标头。

问题在于To标头可能在多行上。

例如:

To: name1@mydomain.org, name2@mydomain.org,
    name3@mydomain.org, name4@mydomain.org, 
    name5@mydomain.org
Message-ID: <46608700.369886.1549009227948@domain.org>

我尝试了以下操作:

sed -n -e '/^[Tt]o: / { N; p; }' _message_file_ |
    awk '{$1=$1;printf("%s ",$0)};NR%2==0{print ""}'

sed命令提取以To和下一行开头的行。 我将输出通过管道传输到awk,以将所有内容放在一行中。

完整命令在一行中输出:

To: name1@mydomain.org, name2@mydomain.org, name3@mydomain.org, name4@mydomain.org

我不知道如何继续测试下一行是否以空格开头并将其添加到结果中。

我想要的是所有地址

To: name1@mydomain.org, name2@mydomain.org, name3@mydomain.org, name4@mydomain.org, name5@mydomain.org

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:2)

formail是一个很好的解决方案,但是以下是使用sed的方法:

sed -e '/^$/q;/^To:/!d;n;:c;/^\s/!d;n;bc' message_file 
  • /^$/q;-(可选)如果标题用尽,则退出
  • /^To:/!d;-如果不是To:标头,请停止处理此行
  • n;-否则,隐式打印它并加载下一行
  • :c;-c是我们可以分支到的标签
  • /^\s/!d;-如果不是继续,请停止处理此行
  • n;-否则,隐式打印它并加载下一行
  • bc-分支回到标签c(即循环)

答案 1 :(得分:1)

我是这样做的:

cat _message_file | formail -X To: | awk '{$1=$1;printf("%s ",$0)};NR%2==0{print ""}'

或者:

formail -X To: < _message_file | awk '{$1=$1;printf("%s ",$0)};NR%2==0{print ""}'

答案 2 :(得分:1)

这可能对您有用(GNU sed):

sed -n '/^To:/{:a;N;/^ /Ms/\s*\n\s*/ /;ta;P}' file

使用-n选项关闭隐式打印。收集以空格开头的行,从换行符To:开始的行中删除换行符两边的空格,并用一个空格替换。如果匹配失败,请在图案空间中打印第一行。

要按原样打印地址,请使用:

sed '/^\S/h;G;/^To:/MP;d' file

答案 3 :(得分:1)

formailreformail都有一个-c选项可以做到这一点。

来自man reformail

-c   Concatenate multi-line headers. Headers split on multiple lines
     are combined into a single line.

因此您无需将输出通过管道传输到awk,只需执行

reformail -c -X To: < $your_message_file

但是,电子邮件通常使用CRLF行结尾,并且由于CR字符,屏幕上的输出可能出现乱码。要删除它们,您可以使用Perl的通用\R行,该行以正则表达式结尾:

reformail -c -X To: < $your_message_file | perl -pe 's/\R/\n/g'

或根据需要在输入上执行以下操作:

perl -pe 's/\R/\n/g' $your_message_file | reformail -c -X To:

在Debian和诸如Ubuntu之类的派生系统上,您可以通过以下方式安装它们

  • apt install maildrop代表reformail,属于Courier's maildrop

  • apt install procmail的{​​{1}}(但procmail现在似乎已被放弃)。