Kevin

用Perl将一堆email的内容整理到excel中去

0
阅读(2957)

每周都要收到很多系统提示邮件,提示我某某老师在系统中进行了捐赠申请或者提出了问题。 装了个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