Perl:读取7个文件并搜索一个单词(文件名称不断变化)

时间:2013-06-05 07:04:16

标签: perl

我每天都会得到一个日志文件,如:

/home/ado/log/log.20130605

日志文件包含项ID和ID的销售次数。 我每天和每周排名。

所以我有一个像这样的日志阅读器

    #!/usr/bin/perl
    use strict;
    use warnings;
    use POSIX 'strftime';

    my $current_date = strftime "%Y%m%d", localtime;
    my $filename     = "/home/ado/log/log.$current_date";

    open my $file, "<", $filename or die("$!: $filename");
    while (<$file>) {
        if (/item_id:(\d+)\s*,\s*start/) {
            $output{$1}++;
        }
    }
    close $file;
    for my $item(keys %output) {
        print "$item -> $output{$item}\n";
    }

我将其保存在数据库中。

我使用cron命令每天运行它。 到目前为止,我每天都要做一些排名。

但每周怎么样?

这意味着制作一个可以同时读取7个文件的新脚本:

    /home/ado/log/log.20130603
    /home/ado/log/log.20130604
    /home/ado/log/log.20130605
    /home/ado/log/log.20130606
    /home/ado/log/log.20130607
    /home/ado/log/log.20130608
    /home/ado/log/log.20130609

搜索正则表达式。然后我会用cron每周运行一次。

如何修改脚本以读取7个文件而不是1个,注意文件名不断变化? - adriancdperu 4分钟前编辑

4 个答案:

答案 0 :(得分:1)

在文件处理周围添加了循环,并在此之前收集所有日志文件,

    #!/usr/bin/perl
    use strict;
    use warnings;
    use POSIX 'strftime';

    # my $current_date = strftime "%Y%m%d", localtime;
    # my $filename     = "/home/ado/log/log.$current_date";
    my @filenames     = reverse sort glob("/home/ado/log/log.*");
    if (@filenames > 7) { $#filenames=6; }

    for my $filename (@filenames) {

      my %output;
      open my $file, "<", $filename or die("$!: $filename");
      while (<$file>) {
          if (/item_id:(\d+)\s*,\s*start/) {
              $output{$1}++;
          }
      }
      close $file;
      for my $item(keys %output) {
          print "$item->$output{$item}\n";
      }

    }

答案 1 :(得分:1)

我建议您使用Time::Piece查找所有相关文件名,并将它们放入@ARGV,就像它们已作为命令行参数输入一样。然后,您可以使用<>来阅读所有这些内容。

喜欢这个

use strict;
use warnings;

use Time::Piece;
use Time::Seconds 'ONE_DAY';

my $today = localtime;
@ARGV = grep {
  /\.(\d{8})$/ and
      $today - Time::Piece->strptime($1, '%Y%m%d') < ONE_DAY * 7;
} glob '/home/ado/log/log.*';

while (<>) {
  ++$output{$1} if /item_id:(\d+)[\s,]*start/;
}

printf "%s -> %s\n", $_, $output{$_} for sort keys %output;

答案 2 :(得分:0)

编写以一组输入文件作为参数的程序,并写入标准输出。

使用7个每日输入文件作为参数调用程序,并将其标准输出重定向到每周摘要。

summarize_files file1 file2 file3 file4 file5 file6 file7 > weekly.summary

您可以将同一程序与每日输入文件一起使用,并将其标准输出重定向到您的每日摘要。

summarize_files file1 > daily.summary

您还可以安排在今天的日期(以天为单位)的两个偏移之间使用文件名来生成输入文件的名称:

 summarize_files -7 -1 > weekly.$(date +%Y%m%d)
 summarize_files -1 -1 > daily.$(date +%Y%m%d)

答案 3 :(得分:0)

使用threads也很有用!

#!/usr/bin/perl

use strict;
use warnings;
use threads;

my ($fh1, $fh2, $fh3, $fh4, $fh5, $fh6, $fh7);
my $thr1 = threads->new(\&sub1, "file1", $fh1);
my $thr2 = threads->new(\&sub1, "file2", $fh2);
my $thr3 = threads->new(\&sub1, "file3", $fh3);
my $thr4 = threads->new(\&sub1, "file4", $fh4);
my $thr5 = threads->new(\&sub1, "file5", $fh5);
my $thr6 = threads->new(\&sub1, "file6", $fh6);
my $thr7 = threads->new(\&sub1, "file7", $fh7);

$thr1->join();
$thr2->join();
$thr3->join();
$thr4->join();
$thr5->join();
$thr6->join();
$thr7->join();

sub sub1 {
    my ($file, $fh) = @_;

    my %output;
    open $fh, "<", $file or die("$!: $file");
    while (<$fh>) {
          if (/item_id:(\d+)\s*,\s*start/) {
              $output{$1}++;
          }
    }
    close $fh;
    for my $item (keys %output) {
        print "$item->$output{$item}\n";
    }
}