我正在尝试在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
任何帮助将不胜感激。
答案 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)
formail
和reformail
都有一个-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现在似乎已被放弃)。