I recently had to split paragraphs across multiple columns. I didn't have long to do it but this solution works quite well so I present it to you ;). I knocked this together quickly so YMMV.

It takes a string of text and assumes paragraphs are on a dual carriage return boundary. It then places these into into columns.

If it helps, set DEBUG to one to see the data structure.
use HTML::Template; use Data::Dumper; use strict; use warnings; use constant DEBUG => 0; my $parser = HTML::Template->new( filehandle => *DATA, die_on_bad_params => 0 ); my $columns = buildColumns( 2, "one\n\ntwo\n\nthree\n\nfour\n\nfive\n\nsix\n\nseven\n\neight" ); print Data::Dumper->Dump([$columns]) if DEBUG; $parser->param( 'columns' => $columns ); print $parser->output(); # # Here you are. # sub buildColumns { my $nc = shift; # Number of columns my @text = @_; # Iterate over the text and split into a more granular array of pa +ragraphs my @paras; foreach my $chunk (@text) { my @parts = split(/\n\n/,$chunk); push @paras,@parts; } my $total = ++$#paras; # Number of paras to go in column one: my $num = 1; if(($total % $nc) % 2 != 0) { $num = int($total/$nc) + ($total % $nc); } else { $num = ($total % $nc); } print "Number into column one is: ", $num, "\n\n" if DEBUG; # Number to go into remainder my $remainder = int($total / $nc); print "Number into remaining columns is: ", $remainder, "\n\n" if +DEBUG; my @columns; my $col = 0; my $pushed = 1; for(my $i = 0; $i < $total; $i++) { unless(defined($columns[$col])) { $columns[$col] = {}; $columns[$col]{'paras'} = []; } if($i >= $num) { # column two (or higher) if($pushed > $remainder) { $col++; print "We have moved to the next column: ", $col, " pu +shed is: ", $pushed,"\n" if DEBUG; $pushed = 1; } } # push into the column push @{$columns[$col]{'paras'}}, {'paragraph'=>$paras[$i]}; $pushed++; print "We have pushed: ", $pushed, "\n" if DEBUG; } return \@columns; } __DATA__ <table> <tr> <TMPL_LOOP NAME="columns"> <td> <TMPL_LOOP NAME="paras"> <p> <TMPL_VAR NAME="paragraph"> <p> </TMPL_LOOP> </td> </TMPL_LOOP> </tr> </table>