http://www.perlmonks.org?node_id=1044932

onelander has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to learn how to turn a hash into a table format.

I realize there are modules that can do this but I am trying to learn how to do it without a module.

The problem is that when a major operation has more than one process the times that the process runs do not end up under the main heading but are being pushed further to the right.

I know the problem has to do with the way I am looping through the hash but I do not know another way to make this work.

I have been thinking that using a format may work but I have not had a chance to test it yet.

#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Data::Dumper; my $debug = 0; my $q_date = "null"; my $operation; my $process; my $date; my $time; my $row_time; my $op_end_time; my %ops_hash; my @ops_array; GetOptions('d:s' => \$q_date, 'x' => \$debug); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; $min = "0" . $min if $min < 10; $hour = "0" . $hour if $hour < 10; $mon += 1; $mon = "0" . $mon if $mon < 10; $year += 1900; if ( $q_date eq "null" ) { $q_date = "$year-$mon-$mday"; } if ( $q_date !~ /\d{4}-\d{2}-\d{2}/ ) { print "Please use a date format of YYYY-MM-DD\n"; exit 1; } my @actlog = <DATA>; print "@actlog" if $debug; foreach my $line ( @actlog ) { next if $line =~ /^$/; chomp ($line); my ($date_time, $message) = split (/,/, $line, 2); ($date, $time) = split (/ /, $date_time); $time =~ s/(\d{2}):\d{2}:\d{2}\.000000/$1/; # save only the hour if ( $time =~ /0(\d)/ ) { $time = $1; # if it is an hour below 10 strip the leading 0 } if ( $message =~ /ANR098[4|5|6|7]I/ ) { $message =~ /Process \d{1,} for ([A-Z ]{1,}|Database Backup)\b +.*PROCESS: (\d{1,})\)/; $operation = $1; $process = $2; $operation =~ s/\s+$//; if ( $message =~ /ANR0984I/ ) { $ops_hash{$date}{"$operation"}{$process}{'start'} = $time; } else { $ops_hash{$date}{"$operation"}{$process}{'end'} = $time; } } } print Dumper(\%ops_hash) if $debug; print "Time,"; foreach my $op ( keys %{ $ops_hash{$q_date} } ) { push (@ops_array, $op); print $op . ","; } print "\n"; for ( 0 .. 23 ) { $row_time = $_; print "$row_time,"; foreach my $op_name ( @ops_array ) { foreach my $op_proc ( keys %{ $ops_hash{$q_date}{$op_name} } ) + { my $op_start_time = $ops_hash{$q_date}{$op_name}{$op_proc} +{'start'}; if ( ! defined $ops_hash{$q_date}{$op_name}{$op_proc}{'end +'} ) { $op_end_time = $hour; } else { $op_end_time = $ops_hash{$q_date}{$op_name}{$op_proc}{ +'end'}; } if ( ( $row_time >= $op_start_time ) && ( $row_time <= $op +_end_time ) ) { print "X:$op_proc,"; } else { print "_,"; } } } print "\n"; } __DATA__ 2013-07-10 00:22:16.000000,"ANR0984I Process 802 for MIGRATION started + in the BACKGROUND at 00:22:16. (SESSION: 91364, PROCESS: 802)" 2013-07-10 00:38:19.000000,"ANR0984I Process 803 for BACKUP STORAGE PO +OL started in the BACKGROUND at 00:38:19. (SESSION: 91367, PROCESS: 8 +03)" 2013-07-10 00:38:25.000000,"ANR0984I Process 804 for SPACE RECLAMATION + started in the BACKGROUND at 00:38:25. (SESSION: 91380, PROCESS: 804 +)" 2013-07-10 00:42:07.000000,"ANR0985I Process 804 for SPACE RECLAMATION + running in the BACKGROUND completed with completion state FAILURE at + 00:42:07. (SESSION: 91380, PROCESS: 804)" 2013-07-10 02:41:09.000000,"ANR0986I Process 803 for BACKUP STORAGE PO +OL running in the BACKGROUND processed 239,441 items for a total of 1 +51,741,110,153 bytes with a completion state of FAILURE at 02:41:09. +(SESSION: 91367, PROCESS: 803)" 2013-07-10 06:16:19.000000,"ANR0984I Process 805 for MOVE DRMEDIA star +ted in the BACKGROUND at 06:16:19. (SESSION: 92271, PROCESS: 805)" 2013-07-10 06:17:12.000000,"ANR0987I Process 805 for MOVE DRMEDIA runn +ing in the BACKGROUND processed 1 items with a completion state of SU +CCESS at 06:17:12. (SESSION: 92271, PROCESS: 805)" 2013-07-10 09:00:38.000000,"ANR0984I Process 806 for PREPARE started i +n the BACKGROUND at 09:00:38. (SESSION: 92686, PROCESS: 806)" 2013-07-10 09:00:39.000000,"ANR0984I Process 807 for EXPIRE INVENTORY +started in the BACKGROUND at 09:00:39. (SESSION: 92687, PROCESS: 807) +" 2013-07-10 09:00:42.000000,"ANR0985I Process 806 for PREPARE running i +n the BACKGROUND completed with completion state SUCCESS at 09:00:42. + (SESSION: 92686, PROCESS: 806)" 2013-07-10 10:00:31.000000,"ANR0987I Process 807 for EXPIRE INVENTORY +running in the BACKGROUND processed 138,657 items with a completion s +tate of SUCCESS at 10:00:31. (SESSION: 92687, PROCESS: 807)" 2013-07-10 10:38:26.000000,"ANR0984I Process 808 for RESTORE VOLUME (P +REVIEW) started in the BACKGROUND at 10:38:26. (SESSION: 92923, PROCE +SS: 808)" 2013-07-10 11:03:11.000000,"ANR0986I Process 808 for RESTORE VOLUME (P +REVIEW) running in the BACKGROUND processed 72,020 items for a total +of 19,033,025,961 bytes with a completion state of SUCCESS at 11:03:1 +1. (SESSION: 92923, PROCESS: 808)" 2013-07-10 13:01:20.000000,"ANR0984I Process 809 for MOVE DATA started + in the BACKGROUND at 13:01:20. (SESSION: 93702, PROCESS: 809)" 2013-07-10 13:16:38.000000,ANR0984I Process 810 for EXPIRE INVENTORY ( +Automatic) started in the BACKGROUND at 13:16:38. (PROCESS: 810) 2013-07-10 13:31:32.000000,"ANR0987I Process 810 for EXPIRE INVENTORY +(Automatic) running in the BACKGROUND processed 13,071 items with a c +ompletion state of SUCCESS at 13:31:32. (PROCESS: 810)" 2013-07-10 14:51:27.000000,"ANR0986I Process 809 for MOVE DATA running + in the BACKGROUND processed 17,017 items for a total of 3,265,383,66 +9 bytes with a completion state of FAILURE at 14:51:27. (SESSION: 937 +02, PROCESS: 809)" 2013-07-10 18:00:06.000000,"ANR0984I Process 811 for Database Backup s +tarted in the FOREGROUND at 18:00:06. (SESSION: 93880, PROCESS: 811)" 2013-07-10 18:00:20.000000,"ANR0984I Process 812 for MOVE DRMEDIA star +ted in the BACKGROUND at 18:00:20. (SESSION: 93881, PROCESS: 812)" 2013-07-10 18:00:21.000000,"ANR0985I Process 812 for MOVE DRMEDIA runn +ing in the BACKGROUND completed with completion state SUCCESS at 18:0 +0:21. (SESSION: 93881, PROCESS: 812)" 2013-07-10 18:00:38.000000,"ANR0984I Process 813 for MOVE DRMEDIA star +ted in the BACKGROUND at 18:00:38. (SESSION: 93884, PROCESS: 813)" 2013-07-10 18:00:38.000000,"ANR0985I Process 813 for MOVE DRMEDIA runn +ing in the BACKGROUND completed with completion state SUCCESS at 18:0 +0:38. (SESSION: 93884, PROCESS: 813)" 2013-07-10 18:00:58.000000,"ANR0984I Process 814 for CHECKIN LIBVOLUME + started in the BACKGROUND at 18:00:58. (SESSION: 93885, PROCESS: 814 +)" 2013-07-10 18:01:04.000000,"ANR0985I Process 814 for CHECKIN LIBVOLUME + running in the BACKGROUND completed with completion state SUCCESS at + 18:01:04. (SESSION: 93885, PROCESS: 814)" 2013-07-10 20:08:14.000000,"ANR0985I Process 811 for Database Backup r +unning in the FOREGROUND completed with completion state SUCCESS at 2 +0:08:14. (SESSION: 93880, PROCESS: 811)" __END__ Hash looks like this '2013-07-10' => { 'MOVE DATA' => { '809' => { 'end' => '14', 'start' => '13 +' } }, 'BACKUP STORAGE POOL' => { '803' => { 'end +' => '2', 'sta +rt' => '0' } }, 'MIGRATION' => { '802' => { 'start' => '0' } }, 'PREPARE' => { '806' => { 'end' => '9', 'start' => '9' } }, 'CHECKIN LIBVOLUME' => { '814' => { 'end' +=> '18', 'start +' => '18' } }, 'SPACE RECLAMATION' => { '804' => { 'end' +=> '0', 'start +' => '0' } }, 'RESTORE VOLUME' => { '808' => { 'end' => +'11', 'start' = +> '10' } }, 'MOVE DRMEDIA' => { '805' => { 'end' => '6 +', 'start' => +'6' }, '812' => { 'end' => '1 +8', 'start' => +'18' }, '813' => { 'end' => '1 +8', 'start' => +'18' } }, 'EXPIRE INVENTORY' => { '810' => { 'end' = +> '13', 'start' + => '13' }, '807' => { 'end' = +> '10', 'start' + => '9' } }, 'Database Backup' => { '811' => { 'end' => + '20', 'start' +=> '18' } } } }; NOTE: The numbers next to the X are just for debugging so they will no +t be part of the actual output. It is there to make it easier to see + where things map out. In the case of the X:812 X:813, only one X sh +ould print. Getting the following Time,MOVE DATA,BACKUP STORAGE POOL,MIGRATION,PREPARE,CHECKIN LIBVOLUME +,SPACE RECLAMATION,RESTORE VOLUME,MOVE DRMEDIA,EXPIRE INVENTORY,Datab +ase Backup, 0,_,X:803,X:802,_,_,X:804,_,_,_,_,_,_,_, 1,_,X:803,X:802,_,_,_,_,_,_,_,_,_,_, 2,_,X:803,X:802,_,_,_,_,_,_,_,_,_,_, 3,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 4,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 5,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 6,_,_,X:802,_,_,_,_,X:805,_,_,_,_,_, 7,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 8,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 9,_,_,X:802,X:806,_,_,_,_,_,_,_,X:807,_, 10,_,_,X:802,_,_,_,X:808,_,_,_,_,X:807,_, 11,_,_,X:802,_,_,_,X:808,_,_,_,_,_,_, 12,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 13,X:809,_,X:802,_,_,_,_,_,_,_,X:810,_,_, 14,X:809,_,X:802,_,_,_,_,_,_,_,_,_,_, 15,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 16,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 17,_,_,X:802,_,_,_,_,_,_,_,_,_,_, 18,_,_,X:802,_,X:814,_,_,_,X:812,X:813,_,_,X:811, 19,_,_,X:802,_,_,_,_,_,_,_,_,_,X:811, 20,_,_,_,_,_,_,_,_,_,_,_,_,X:811, 21,_,_,_,_,_,_,_,_,_,_,_,_,_, 22,_,_,_,_,_,_,_,_,_,_,_,_,_, 23,_,_,_,_,_,_,_,_,_,_,_,_,_, I am expecting to get the following. Time,MOVE DATA,BACKUP STORAGE POOL,MIGRATION,PREPARE,CHECKIN LIBVOLUME +,SPACE RECLAMATION,RESTORE VOLUME,MOVE DRMEDIA,EXPIRE INVENTORY,Datab +ase Backup, 0,_,X:803,X:802,_,_,X:804,_,_,_,_, 1,_,X:803,X:802,_,_,_,_,_,_,_, 2,_,X:803,X:802,_,_,_,_,_,_,_, 3,_,_,X:802,_,_,_,_,_,_,_, 4,_,_,X:802,_,_,_,_,_,_,_, 5,_,_,X:802,_,_,_,_,_,_,_, 6,_,_,X:802,_,_,_,_,X:805,_,_, 7,_,_,X:802,_,_,_,_,_,_,_, 8,_,_,X:802,_,_,_,_,_,_,_, 9,_,_,X:802,X:806,_,_,_,_,X:807,_, 10,_,_,X:802,_,_,_,X:808,_,X:807,_, 11,_,_,X:802,_,_,_,X:808,_,_,_, 12,_,_,X:802,_,_,_,_,_,_,_, 13,X:809,_,X:802,_,_,_,_,_,X:810,_, 14,X:809,_,X:802,_,_,_,_,_,_,_, 15,_,_,X:802,_,_,_,_,_,_,_, 16,_,_,X:802,_,_,_,_,_,_,_, 17,_,_,X:802,_,_,_,_,_,_,_, 18,_,_,X:802,_,X:814,_,_,"X:812, X:813",_,X:811, 19,_,_,X:802,_,_,_,_,_,_,X:811, 20,_,_,_,_,_,_,_,_,_,X:811, 21,_,_,_,_,_,_,_,_,_,_, 22,_,_,_,_,_,_,_,_,_,_, 23,_,_,_,_,_,_,_,_,_,_,