use strict; use warnings; use Data::Dumper; my $hash; while(){ chomp; my @fields = split /\s+/; my ($agency,$url,$mod) = @fields[2,3,6]; my ($user,$state) = @fields[1,5]; my $item = $hash->{$agency}{$url}{$mod}; if($state eq 'pass'){ $hash->{$agency}{$url}{$mod}{pass} += 1; }elsif($state eq 'fail'){ $hash->{$agency}{$url}{$mod}{fail} += 1; } elsif($state =~ /new_/){ $hash->{$agency}{$url}{$mod}{new} += 1; } $hash->{$agency}{$url}{$mod}{users}{$user} += 1 if $state ne 'fail'; } print join "\t" => qw(Agency URL Pass Fail New Unique Module),"\n"; foreach my $agency (keys %{$hash}){ foreach my $url (keys %{$hash->{$agency}}){ foreach my $mod (keys %{$hash->{$agency}{$url}}){ my $item = $hash->{$agency}{$url}{$mod}; my $pass = $item->{pass} || 0; my $fail =$item->{fail} || 0; my $new = $item->{new} || 0; my $unique =scalar keys %{$item->{users}}; print join "\t" => ($agency,$url,$pass,$fail,$new,$unique,$mod),"\n"; } } } __DATA__ 05/Jun/2003:00:01:23 user1 agency1 url1 garbage pass mod1 more_garbage 05/Jun/2003:00:03:17 user2 null url1 garbage fail mod1 more_garbage 05/Jun/2003:00:03:42 user1 agency1 url1 garbage pass mod1 more_garbage 05/Jun/2003:00:05:03 user6 agnecy2 url1 garbage pass mod1 more_garbage 05/Jun/2003:00:08:34 user3 agnecy2 url1 garbage pass mod1 more_garbage 05/Jun/2003:00:11:59 user4 agency2 url2 garbage fail mod1 more_garbage 05/Jun/2003:00:14:30 user5 agnecy2 url1 garbage new_a mod1 more_garbage 05/Jun/2003:00:15:02 user1 agency1 url1 garbage pass mod1 more_garbage 05/Jun/2003:00:16:56 user7 agency2 url2 garbage pass mod2 more_garbage 05/Jun/2003:00:17:31 user1 agency1 url1 garbage fail mod1 more_garbage 05/Jun/2003:00:17:31 user1 agency1 url1 garbage pass mod2 more_garbage