Reputation:
I have a Perl code responsible for formatting output. Problem is I need to calculate correct number of tabs to be put before one particular character in each string (let's say it's /). So instead of getting lines with different lengths I'd like to get fixed-length strings (but as short as possible, using the longest as max). How should I approach this?
Example of output (with format commented out, just raw array):
Long title with some looong words / short text Another title / another short text
I need it like this:
title with some looong words / short text
Different title / another short text
This was my first attempt, but it didn't involve using tabs after one particular character.
my $text = Text::Format->new;
$text->rightAlign(1);
$text->columns(65);
$text->tabstop(4);
$values[$i] = $text->format(@values[$i]);
Upvotes: 2
Views: 3690
Reputation: 107040
There are two generally accepted ways to format text in Perl, so columns line up:
printf
and sprintf
. This is probably the most common way it's done.I haven't seen people use Perl Format specifications stuff in years. It was a big feature back in Perl 3.x heydays because Perl was mainly used as a super-awk replacement language(Practical Extraction and Reporting Language). However, the mechanism is still there, and I'm sure it'll be fun to learn.
Now comes the second part of your query. You really don't merely want the text to be formatted, you want it to be formatted with tabs.
Fortunately, Perl has a built in module called Text::Tabs. It's one of those modules that does one or two obscure tasks, but does them well.
Actually, Text::Tabs
doesn't handle the two tasks it does well, but adequately.
Produce your report using sprintf
or the build in Perl formatting capabilities. Save your whole report in an array. It has to be an array because Text::Tabs
doesn't handle NLs. Then use the unexpand
function to replace spaces in that array into another array with tabs.
WORD 'O WARNING: Text::Tabs
does something very naughty: It imports the variable $tabstop
into your program without asking your permission. If you use a variable called $tabstop
, you'll have to change it. You can set $tabstop
to be the number of spaces a tab represents. It's set to 8 as a default.
Upvotes: 2
Reputation: 30831
From what I can find in the documentation Text::Format only does paragraph formatting. What you want is a tabular format. The basic approach to that is to split your data into a matrix of text for each row & column, find the longest element for each column, and use that to output fixed width data. e.g.:
my @values = (
'Long title with some looong words / short text',
'Another title / another short text',
);
# split values into per-column text
my @text = map { [ split '\s*(/)\s*', $_ ] } @values;
# find the maximum width of each column
my @width;
foreach my $line (@text) {
for my $i (0 .. $#$line) {
no warnings 'uninitialized';
my $l = length $line->[$i];
$width[$i] = $l if $l > $width[$i];
}
}
# build a format string using column widths
my $format = join ' ', map { "%-${_}s" } @width;
$format .= "\n";
# print output in columns
printf $format, @$_ foreach @text;
This produces the following:
Long title with some looong words / short text
Another title / another short text
Upvotes: 0
Reputation: 241868
The module Text::Table might help you.
#!/usr/bin/perl
use warnings;
use strict;
use Text::Table;
my @array = ('Long title with some looong words', 'short text',
'Another title', 'another short text');
my $table = Text::Table::->new(q(), \' / ', q()); # Define the separator.
$table->add(shift @array, shift @array) while @array;
print $table;
Upvotes: 0