Count rows based on header and date

I have a tab delimited file with this format:

Business System Name:  OK_CR                      

Serial Numbr  Service Name          Program Name          Epoch Start Time     
------------  --------------------  --------------------  -------------------  
GI1001TAA266  PPV 10 (50106)        We Bought A Zoo       Aug 14 2012  4:15AM  
GI1002TB3596  PPV 5 (50101)         Help, The (2011)      Aug 14 2012  6:30PM  
GI1002TDH825  PPV 2 (50098)         Safe House            Sep  7 2012  2:15AM  

Business System Name:  OK_SV                      

Serial Numbr  Service Name          Program Name          Epoch Start Time     
------------  --------------------  --------------------  -------------------  
GI1001TAA266  PPV 10 (50106)        We Bought A Zoo       Aug 14 2012  4:15AM  
GI1002TB3596  PPV 5 (50101)         Help, The (2011)      Aug 14 2012  6:30PM  
GI1002TDH825  PPV 2 (50098)         Safe House            Sep  7 2012  2:15AM  

I want to count the number of rows by date, separated by the header of the business system, I mean, the result of the script should look like this:

Business System Name:  OK_CR
Aug 14: 2
Sep 7: 1

Business System Name:  OK_SV
Aug 14: 2
Sep 7: 1

So far I have created a hash, but I am amazed at how to count each date and reset the counter after each header of the business system. This is my script:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

open my $fh, '<', 'ppv.txt' or die $!;

my %data;
my $sect;
while (<$fh>) {
  next if /^\s+/;
  if (/^Business System Name:\s+(\w+)/) {
    $sect = $1;
    next;
  }
  #print "$sect\n";
  if (defined $sect) {
    next if /^Serial Numbr/;
    next if /^------------/;
    push @{ $data{$sect} }, $_;
  }
}
print Dumper \%data;

This is the result of the script:

$VAR1 = {
          'OK_CR' => [
                       'GI1001TAA266  PPV 10 (50106)        We Bought A Zoo       Aug 14 2012  4:15AM
',
                       'GI1002TB3596  PPV 5 (50101)         Help, The (2011)      Aug 14 2012  6:30PM
',
                       'GI1002TDH825  PPV 2 (50098)         Safe House            Sep  7 2012  2:15AM
'
                     ],
          'OK_SV' => [
                       'GI1001TAA266  PPV 10 (50106)        We Bought A Zoo       Aug 14 2012  4:15AM
',
                       'GI1002TB3596  PPV 5 (50101)         Help, The (2011)      Aug 14 2012  6:30PM
',
                       'GI1002TDH825  PPV 2 (50098)         Safe House            Sep  7 2012  2:15AM
'
                     ]
        };

Any idea on how to move from here?

+4
source share
3 answers

Using unpack, as in your comment, you just need to keep track of the number for each date:

use strict;
use warnings;
use Data::Dumper;

open my $fh, '<', 'ppv.txt' or die $!;

my %data;
my $sect;
while (<$fh>) {
  next if /^\s+/;
  if (/^Business System Name:\s+(\w+)/) {
    $sect = $1;
    next;
  }
  #print "$sect\n";
  if (defined $sect) {
    next if /^Serial Numbr/;
    next if /^------------/;
    my $format = 'A57 A13 A*';
    my($prefixes, $date, $suffixes) = unpack($format, $_);
    $data{$sect}{$date}++;
  }
}
print Dumper \%data;

__END__

$VAR1 = {
          'OK_CR' => {
                       ' Aug 14 2012' => 2,
                       ' Sep  7 2012' => 1
                     },
          'OK_SV' => {
                       ' Aug 14 2012' => 2,
                       ' Sep  7 2012' => 1
                     }
        };
+1
source

This should work:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %hash =();
open(FILE,"test.txt");
while(<FILE>)
{
    if(/(Business System Name:\s+OK_\S+)\s+/)
    {
        if(%hash)
        {
            print Dumper \%hash;
            %hash=();
            $hash{header}=$1;
        }
        else
        {
            $hash{header}=$1;
        }
    }
    elsif(/((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d+\s+\d\d\d\d)/)
    {
        if(defined $hash{$1}){$hash{$1}++;}
        else{$hash{$1}=1;}
    }
}
close(FILE);
if(%hash)
{
    print Dumper \%hash;
}

exit:

$VAR1 = {
          'Aug 14 2012' => 2,
          'Sep  7 2012' => 1,
          'header' => 'Business System Name:  OK_CR'
        };
$VAR1 = {
          'Aug 14 2012' => 2,
          'Sep  7 2012' => 1,
          'header' => 'Business System Name:  OK_SV'
        };
+1
source

, Perl ($/) " -:", . , split \t, , :

use strict;
use warnings;
use Data::Dumper;

local $/ = 'Business System Name:';
my %data;

while (<>) {
    my ($sect) = /\s+(.+)/;
    my @timeLines = grep /:\d\d(?:A|P)M$/, split /\n/;
    for (@timeLines) {
        ( split /\t/ )[-1] =~ /(.+?)\s+\d+:/;
        $data{$sect}{$1}++;
    }
}

print Dumper \%data

: perl script.pl inFile [>outFile]

.

The output in your dataset is:

$VAR1 = {
          'OK_SV                      ' => {
                                             'Aug 14 2012' => 2,
                                             'Sep  7 2012' => 1
                                           },
          'OK_CR                      ' => {
                                             'Aug 14 2012' => 2,
                                             'Sep  7 2012' => 1
                                           }
        };

After recording, the section name will be fixed. Then record lines splitin new lines and grepped only for those lines that contain time data. The last cycle for spliton the tab character, receives the last field, captures the date information and then increases the hash with the sect and date data.

Hope this helps!

+1
source

All Articles