每周都要收到很多系统提示邮件,提示我某某老师在系统中进行了捐赠申请或者提出了问题。 装了个google desktop, 基本上可以不访问数据库就能解决不少老师的捐赠查询问题。
但是,如果需要更多的组合信息,就需要将数百个email内容,根据关键词,进行信息整理,导出到 excel表格中去,方便查找和管理。
以前我用gawk这种比较原始的语言干过类似的事,最近有空,研究了一下如何用perl做。
为简单起见和保持可移植性,没有引入复杂的操作,而是直接用文本操作搞定。
过程如下:
1.在windows下建立perl环境
1.1安装ActivePerl
1.2安装集成环境Perl Express
2.把数百个email打包为一个email.
同时选中所有关心的email, 转发,这样所有的email就作为附件存在一个汇总的email里了。 然后,将此email另存为msg格式。
3.用Perl处理
采用Text::CSV_XS包进行CSV格式的文件处理,得到excel认识的CSV文件.
将总email文件强行当作文本文件打开, 由于email里面我关心的信息,目前用=分隔,比如lastname=xie, 因此,new了一个用"="做分隔符的CSV类。 有些我关心的信息用":"做分隔符,因此new了一个用":"做分隔符的CSV类, 另外,输出文件格式是标准的用逗号为分隔符的CSV,因此new了一个不带参数缺省的类。
然后生成表头,扫描整个文件,碰见lastname= firstname= 之类的关键词,放到相应的地方。 碰见自由书写的地方,用正则表达式匹配,翻译成统一的表达方式,把email信头中的时间格式裁剪转换为excel表格认识的日期格式。
生成的outputfile.csv可以拷贝到xls文件中进一步处理。
4.遇到的问题
4.1 Text::CSV_XS和Text::CSV
最初抄的例程用的是Text::CSV,在ActivePerl默认的安装中并没有,取而代之的是编译版本的Text::CSV_XS,实践证明,Text::CSV_XS比Text::CSV快将近10倍。
4.2 Perl Express 的路径设置
一开始用Perl Express跑程序,无法打开本地目录的测试msg文件,原因是需要在Perl Express菜单中设置工作路径,Perl->excution directory->select 中,设置工作路径即可。
5.讨论
5.1 Perl还有很多更复杂的包,可以处理email,excel等,也可以用,只不过,用简单的Text::CSV搞定,性能也很好,目前俺就不深入了。
5.2
以下是代码:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
my $NUMBER=0;
my $REQDATE=1;
my $SCHOOL=2;
my $PROF=3;
my $EMAIL=4;
my $REQUEST=5;
my $csv_emailheader = Text::CSV_XS->new({'sep_char' => ':'
});
my $csv = Text::CSV_XS->new({'sep_char' => '='
});
my $outcsv = Text::CSV_XS->new();
my $infile = 'chinaapprovals.msg';
system("dir");
open (INFD, "<", $infile) or die $!;
my $outfile='outputfile.csv';
open (OUTFD, ">", $outfile) or die $!;
my @array;
my $id=1;
$array[$NUMBER]='number';
$array[$REQDATE]='req date';
$array[$SCHOOL]='school';
$array[$PROF]='prof';
$array[$EMAIL]='email';
$array[$REQUEST]='request';
$outcsv->combine(@array);
print OUTFD $outcsv->string()."\n";
my @columns;
while (<INFD>) {
if ($csv->parse($_)) {
@columns = $csv->fields();
if($columns[0] =~ /^ firstname $/){
$array[$PROF]=$columns[1];
}
if($columns[0] =~ /^ lastname $/){
$array[$PROF]=$array[$PROF].$columns[1];
}
if($columns[0] =~ /^ email $/){
$array[$EMAIL]=$columns[1];
}
if($columns[0] =~ /^ company $/){
$array[$SCHOOL]=$columns[1];
}
if($columns[0] =~ /^ req_software $/){
if ($columns[1] =~ /No softwareI/)
{
$array[$REQUEST]="";
}else{
$array[$REQUEST]="SW".$columns[1];
}
}
if($columns[0] =~ /^ software_qty $/){
if ($columns[1] =~ /[0-9]+/)
{
$array[$REQUEST]=$array[$REQUEST].$columns[1]."Lc";
}
}
if($columns[0] =~ /^ req_board $/){
if ($columns[1] =~ /No boards/){
$array[$REQUEST]=$array[$REQUEST]."";
}else{
if ($columns[1] =~ /Digilent S3E/){
$array[$REQUEST]=$array[$REQUEST]." S3E ";
}else{
$array[$REQUEST]=$array[$REQUEST]."";
}
}
}
if($columns[0] =~ /^ board_qty $/){
if($columns[1] =! /"How Many Boards"/){
$array[$REQUEST]=$array[$REQUEST].$columns[1]."pcs";
}
}
if($columns[0] =~ /^ other_products $/){
$array[$REQUEST]=$array[$REQUEST]." ".$columns[1];
}
if($columns[0] =~ /^ Comments $/){
$array[$REQUEST]=$array[$REQUEST]." ".$columns[1];
}
}
if($csv_emailheader->parse($_)) {
@columns = $csv_emailheader->fields();
if($columns[0] =~ /X-OriginalArrivalTime/){
$array[$REQDATE]= $columns[1];
$array[$REQDATE]=~ s/..$//;
$array[$REQDATE]=~ s/ /-/;
$array[$REQDATE]=~ s/^-//;
$array[$REQDATE]=~ s/-$//;
$array[$NUMBER]=$id++;
$outcsv->combine(@array);
print OUTFD $outcsv->string()."\n";
}
}
}
close INFD;
close OUTFD;
print "done\n";