很抱歉问了很多次关于阅读线和其他东西的问题。我碰巧正在处理这样一个巨大的(500,000行)文件:
2013-05-27T19:01:23 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:29 [INFO] item_id:2, pause at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
我需要做的是,在文件位置作为输入的情况下,创建一个输出类似于以下内容的脚本:
$output = [ {item_id => 1, counter => 2 }, { item_id......
也就是说,每个item_id应该与数组ref中的启动次数配对。请注意,我不能使用“while”多次读取文件,因为它太大了。另外,我不知道有多少项目。
我使用Stackoverflow成员提示编写的方法如下:
sub count_start{
open LOGFILE, $file_location;
my $max;
my $i;
my $counter = 0;
my $found = 0;
my $data;
while (<LOGFILE>) {
next unless /item_id:(\d+)/;
$found = $1 if $found < $1;
for ($i =1, $i<=$found, $i++){
if ($file_location =~ /\bitem_id:$i, start\b/ig){
$counter++;
}
$output = [ $i => $counter ];
}
}
close LOGFILE;
return $output;
}
1;
但是一切都变得非常错误:(。我收到了很多令人讨厌的警告,没有任何类似于我的要求。任何想法或建议?
原谅这个perl新手,因为他糟糕的代码。
答案 0 :(得分:1)
您不能在列表中添加类似哈希的关联。为此你需要一个哈希:
use strict;
use warnings;
my %output;
my $filename = shift @ARGV;
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 -> 5
3 -> 3
5 -> 4
您可以使用以下方法替换while循环:
/item_id:(\d+)\s*,\s*start/ and $output{$1}++ while <$file>;
但它不是真的可读。
答案 1 :(得分:1)
我会使用哈希来进行计数,然后将其转换为哈希数组。但是,看起来您使用perl代码来存储数据,这不是最好的主意。有更好的格式,例如JSON
,甚至Text::CSV
。
除此之外,Data::Dumper
模块可用于此目的。
use strict;
use warnings;
use Data::Dumper;
my %output;
while (<DATA>) {
if (/ item_id:(\d+), start at /) {
$output{$1}++;
}
}
my @data = map { { item_id => $_, counter => $output{$_} } } keys %output;
print Dumper \@data;
__DATA__
2013-05-27T19:01:23 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:29 [INFO] item_id:2, pause at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:1, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:3, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
2013-05-27T19:01:30 [INFO] item_id:5, start at Reader.pm line 23
<强>输出:强>
$VAR1 = [
{
'counter' => 5,
'item_id' => '1'
},
{
'counter' => 3,
'item_id' => '3'
},
{
'counter' => 5,
'item_id' => '5'
}
];
请注意,由于散列未排序,输出未排序。如果要对其进行排序,可以将sort
功能应用于键。
另请注意,此版本考虑到您说要计算“开始”,其中此输入不包括显示item_id:2, pause at
的第2行。