Perl脚本从多个txt文件中读取和打印行?

时间:2011-08-24 14:30:33

标签: perl file

我们有300多个txt文件,其中基本上是电子邮件的复制品,每个txt文件都有以下格式:

To: blabla@hotmail.com 
Subject: blabla 
From: bla1@hotmail.com 
Message: Hello World! 

我在脚本上的平台是Windows,一切都是本地的(包括Perl实例)。目的是编写一个脚本,该脚本遍历每个文件(都位于同一目录中),并在from字段中打印出每个“唯一”电子邮件地址的列表。这个概念很简单。

有人能指出我在正确的方向吗?我知道如何开始Perl脚本,我能够读取单个文件并打印所有细节:

 #!/usr/local/bin/perl
 open (MYFILE, 'emails/email_id_1.txt');
 while (<MYFILE>) {
    chomp;
    print "$_\n";
 }
 close (MYFILE);

现在,我需要能够读取和打印此文件的第3行,但不仅要执行此活动一次,而且要执行所有文件。我查看了File :: Find模块,这可能有用吗?

5 个答案:

答案 0 :(得分:2)

内置glob()可以为您提供目录中的文件列表:

chdir $dir or die $!;
my @files = glob('*');

您可以使用Tie::File访问文件的第3行:

use Tie::File;

for (@files) {
    tie my @lines, 'Tie::File', $_ or die $!;
    print $lines[2], "\n";         
}

答案 1 :(得分:2)

什么平台?如果Linux那么简单:

foreach $f (@ARGS) {    
    # Do stuff 
}

然后拨打:

perl mything.pl *.txt

在Windows中,您需要首先展开通配符,因为cmd.exe不会扩展通配符(与Linux shell不同):

@ARGV = map glob, @ARGV

foreach $f (@ARGS) {
    # Do stuff
}

然后提取第三行只是读取每一行的简单情况,并在你到达第3行时进行计数,以便你知道打印结果。

答案 2 :(得分:2)

Perl one-liner,windows-version:

perl -wE "@ARGV = glob '*.txt'; while (<>) { say $1 if /^From:\s*(.*)/ }"

它将检查所有行,但只有在找到有效的From:标记时才会打印。

答案 3 :(得分:1)

您使用的是Unix风格的shell吗?您可以在shell中执行此操作,甚至不使用Perl。

  

grep“^ From:”。/ * |排序| uniq -c“

细分如下:

  1. grep会抓住以“From:”开头的每一行,并将其发送给......
  2. sort,它会对这些行进行alpha排序,然后......
  3. uniq,将过滤出欺骗线。 “-c”部分将计算出现次数。
  4. 您的输出看起来像:     

        3 From: dave@example.com
        5 From: foo@bar.example.com
        etc...

    可能的问题: 我不确定你的“From”行会有多复杂,例如:多个地址,不同格式等。

    您可以通过几种方式增强该grep步骤,或者将其替换为功能不如您提议的多功能一体脚本的Perl脚本。

    如果有任何不清楚的地方,请发表评论。

答案 4 :(得分:1)

这是我的解决方案(我希望这不是作业)。

它检查当前目录中名称以“.txt”结尾的所有文件,不区分大小写(例如,它会找到“foo.TXT”,这可能是您在Windows下所需的)。它还允许行终止符(至少CR-LF和LF)的可能变化,并且不区分大小写地搜索From:前缀,并允许:之后的任意空格。

#!/usr/bin/perl

use strict;
use warnings;

opendir my $DIR, '.' or die "opendir .: $!\n";
my @files = grep /\.txt$/i, readdir $DIR;
closedir $DIR;
# print "Got ", scalar @files, " files\n";

my %seen = ();
foreach my $file (@files) {
    open my $FILE, '<', $file or die "$file: $!\n";
    while (<$FILE>) {
        if (/^From:\s*(.*)\r?$/i) {
            $seen{$1} = 1;
        }
    }
    close $FILE;
}

foreach my $addr (sort keys %seen) {
    print "$addr\n";
}