use 5.020; use warnings; use Template; my $data = [[ qw(1 2 A 4) ], [ qw(3 4 A 5) ], [ qw(5 5 B 2) ], [ qw(6 2 B 3) ], [ qw(1 2 C 2) ], [ qw(2 3 C 2) ], [ qw(1 3 C 1) ], ]; my $template = <<'EOT'; [% SET category = ''; FOREACH line IN data; IF line.2 != category; GET line.2; "\n"; category = line.2; END; GET line.join(" "); "\n"; END; %] EOT my $tt = Template->new; $tt->process(\$template,{data => $data}); #### { A => [[qw(1 2 A 4)],[qw(3 4 A 5)]], B => [[qw(5 5 B 2)],[qw(6 2 B 3)]], C => [[qw(1 2 C 2)],[qw(2 3 C 2)],[qw(1 3 C 1)]], } #### use 5.020; use warnings; use Template; my $data = [[ qw(1 2 A 4) ], [ qw(3 4 A 5) ], [ qw(5 5 B 2) ], [ qw(6 2 B 3) ], [ qw(1 2 C 2) ], [ qw(2 3 C 2) ], [ qw(1 3 C 1) ], ]; my %munged; for my $record (@$data) { no warnings "uninitialized"; push @{$munged{$record->[2]}}, $record; } my $template = <<'EOT'; [% FOREACH category IN data.keys.sort; GET category; "\n"; FOREACH record IN data.$category; GET record.join(" ");"\n"; END; END; %] EOT my $tt = Template->new; $tt->process(\$template,{data => \%munged});