views:

330

answers:

6

Often in Perl I want to print out column/row data, say, from a hash.

This is simple:

foreach my $k(keys %h)
{
  print $k, "\t", $h{$k}, "\n";
}

However, if the key happens to have a varying length, then the formatting just looks very jagged. I've investigated format, and its typically too heavyweight for what I'm looking for, which is a 'simple' column-row aligning pretty-printer.

+15  A: 

I think you'll find printf usefull. Here is a small example:

printf("%10s\t%10s\n", $k, $h{$k});
## prints "         key\t         value\n"
## prints "  longer_key\t  longer_value\n"

Long values are not truncated, and you can change text aligment inside block:

  • %10s - means string type of length 10 (left aligned)
  • %-10s - means string type of length 10 (right aligned)

Full list of formats is on sprintf man page.

Ivan Nevostruev
+3  A: 

Probably not an optimal solution, but you'll need to find your max key and max value lengths, and then pass them to either sprintf or pack. Or you could use static max lengths if your data source has "reasonable" constraints (eg. column length limits in a database etc)

Aquatoad
+6  A: 

Check out the x operator (documented at perldoc perlop), useful for simple formatting tasks that involve padding fields to a specific length:

while ((my $key, $value) = each %h)
{
    print $key . (" " x (20 - length $key)) . $value, "\n";
}

You can also use sprintf or printf (perldoc -f sprintf, perldoc -f printf) (with these you can also pad with zeros in numbers):

while ((my $key, $value) = each %h)
{
    printf("%20s %20s\n", $key, $value);
}
Ether
+5  A: 

If you want a heavy-duty solution, there are modules like Text::Table.

Kinopiko
+3  A: 

The robust solution requires two passes: one to determine the length of the longest key, the other to print the output:

my $l = 0;
foreach my $key (keys %hash) {
    $l = length($key) if length($key) > $l;
}

foreach my $key (keys %hash) {
    printf "%-${l}s  %s\n", $key, $hash{$key};
}

If you know the upper limit of the key lengths ahead of time, you can avoid the first loop.

Michael Carman
+2  A: 

I know you said format might be too heavy-weight, but it might actually be less complex. Try something like this:

foreach my $k(keys %h) {
  format =
  Key:  @<<<<<<<<<<<<<<<< Value:  @>>>>>>>>>>>>>>>>>
  $k,                     $h{$k}  
  .

  write;
}

Hope this helps!!

Shez