foreach my $td (@tds) { say for @$td; } #### use strict; use warnings; use Data::Dumper; use HTML::TreeBuilder; my $h = HTML::TreeBuilder->new; $h->parse_content( do{ local $/; } ); my @headers = map @{ $_->content }, $h->look_down( class => qr/HeaderTitle\b/ ) ; my @matched = map ref $_ ? @$_ : $_, map $_->content, $h->look_down( _tag => 'td', class => qr/Alt(Warning|Error)\b/ ) ; my @tmp = map[ @matched[ $_ .. $_ + @headers - 1] ], range( 0, $#matched, scalar(@headers) ) ; my @records; for (@tmp) { my %hash; @hash{@headers} = @$_; push @records, {%hash}; } print Dumper \@records; sub range {grep!(($_-$_[0])%($_[2]||1)),$_[0]..$_[1]} __DATA__
  Status Results Schedule Start Actual Start Schedule Name Node Name Domain Name
Completed Successful 2015-05-11-17.00 2015-05-11-17.10 DAILYBACKUP_5PM ServerA ST10_DOMAIN
Missed 2015-05-11-18.00 DAILYBACKUP_6PM ServerB ST10_DOMAIN
Missed 2015-05-11-18.00 NJDLYBACKUP_6PM ServerC ST13_DOMAIN
QATSWAS85 37899 104,113 617 0 0 0 25 13 251.30 MB 00:00:58 4,378.98 0%
ServerD 38048 31,461 51 0 0 0 2 2 24.14 MB 00:00:12 1,946.00 0%
##
## $VAR1 = [ { 'Actual Start' => undef, 'Node Name' => 'ServerB', 'Results' => undef, 'Schedule Name' => 'DAILYBACKUP_6PM', 'Schedule Start' => '2015-05-11-18.00', 'Domain Name' => 'ST10_DOMAIN', 'Status' => 'Missed' }, { 'Schedule Start' => '2015-05-11-18.00', 'Results' => undef, 'Domain Name' => 'ST13_DOMAIN', 'Schedule Name' => 'NJDLYBACKUP_6PM', 'Status' => 'Missed', 'Node Name' => 'ServerC', 'Actual Start' => undef } ]; ####