【问题标题】:How to extract email headers extending on multiple lines from file如何从文件中提取多行扩展的电子邮件标题
【发布时间】:2020-10-07 04:29:39
【问题描述】:

我正在尝试在 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

任何帮助将不胜感激。

【问题讨论】:

标签: linux email awk sed grep


【解决方案1】:

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(即循环)

【讨论】:

  • 是的,如果我们只是在 To 前面添加一个小 ^ 就可以工作,否则它将打印文件中包含 To 的第一行。现在的命令是: sed -e '/^$/q;/^To:/!d;n;:c;/^\s/!d;n;bc' _message_file
  • 抱歉,打错了。当然应该有一个^(它在评论中!)。
  • 只是一件小事。该命令最后添加了一个额外的空格。但我能找到的最简单的解决方案是:formail -X To:
  • @potong sed '/^\S/h;G;/^To:/MP;d' file 提出的命令只需几个动作就可以完成这项工作
【解决方案2】:

我是这样做的:

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 ""}'

【讨论】:

  • 是的,你是对的。我们可以这样做: formail -X To:
【解决方案3】:

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 procmailformail(但procmail 现在似乎已被放弃)。

【讨论】:

    【解决方案4】:

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

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

    使用-n 选项关闭隐式打印。收集以空格开头的行,删除换行符两侧的空格并将其替换为一个空格,从以To: 开头的行开始。当匹配失败时,打印模式空间的第一行。

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

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

    【讨论】:

    • 第二个命令成功了!第一个只打印第一行。谢谢
    • 好的,第二个有点令人费解:) 我想它主要是可移植的(虽然不是那么短!)如果写成:sed '/^[^ ^T]/h;G;/\nTo:/P;d' file 其中^T 是文字制表符
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 2013-01-24
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    相关资源
    最近更新 更多