I have an input of the following format:
09:08:11 XXXXXXXXXXXXX 1.1.1.1
09:09:03 YYYYYYYY 2.2.2.2
09:12:37 ZZZZ 3.3.3.3
I am able to extract these individuals fields easily using the regex /(\S+)\s+(\S+)\s+(\S+)\s+/
. I named them $time
, $name
, and $number
. My problem is I want to display this so that the $number
aligns perfectly. Because the $name
can be of any length, what is the best solution for this?
I would like for the output to look like this. Please note that I had to use dots to align the last field since I wasn't able use the spacebar to do this, not sure why. Anyhoo.
09:08:11 XXXXXXXXXXXXX 1.1.1.1
09:09:03 YYYYYYYY 2.2.2.2
09:12:37 ZZZZ 3.3.3.3
I thought about putting the $name
into an array. And then use a function to find the one with the longest character count. Finally I would pad out the shorter name to match the longest name. Is there a better and more efficient way to do this?
For formatting, try using the sprintf function, as in
$line = sprintf "%-12s %-20s %-s\n", $time, $name, $number;
(the minus sign means left-justify)
It was given by someone here:
my($name, $telephone, $stime);
format Infos =
@<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<
$name, $telephone, $stime
.
$~ = 'Infos';
($name, $telephone, $stime) = ('Name:', 'Telephone:', 'Start Time:');
write;
($name, $telephone, $stime) = ('Mike Bax', 'tel-41596', 'Fri 8/22 13:31');
write;
You can change variables names, and it should work for you.
Have a look at Perl6::Form.
This is the recommended approach over using format. See this previous Stack Overflow answer: What other languages have features and/or libraries similar to Perl's format?
Here is an example of Perl6::Form doing just what you want with your data:
use Perl6::Form;
my ($time, $name, $number);
my @data = (
[ qw(09:08:11 XXXXXXXXXXXXX 1.1.1.1) ],
[ qw(09:09:03 YYYYYYYY 2.2.2.2) ],
[ qw(09:12:37 ZZZZ 3.3.3.3) ],
);
for my $line (@data) {
push @$time, $line->[0];
push @$name, $line->[1];
push @$number, $line->[2];
}
print form
'{[[[[[[} {[[[[[[[[[[[[[[[[[[[[} {[[[[[[}',
$time, $name, $number;
NB. If your data fields ever become larger than the form fields specified then you will run into formatting issues (and same thing also applies to sprintf and format solutions).
It's easy to fix depending on what your output requirements are. For example, if you want to maintain tabular stability then...
print form { layout => 'tabular' },
'{[[[[[[} {[[[[[[[[[[[[[[[[[[[[} {[[[[[[}',
$time, $name, $number;
...will word wrap each column for you.
If you do not know the maximum width of the middle field, you will have to make two passes over the data as @ijw notes.
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw( :seek );
my $max_length = 0;
my $data_pos = tell DATA;
while ( my $line = <DATA> ) {
last unless $line =~ /\S/;
my $name = (split ' ', $line)[1];
my $name_length = length $name;
$max_length = $name_length if $name_length > $max_length;
}
seek DATA, $data_pos, SEEK_SET;
while ( my $line = <DATA> ) {
last unless $line =~ /\S/;
my ($date, $name, $ip) = split ' ', $line;
printf "%s %-${max_length}s %s\n", $date, $name, $ip;
}
__DATA__
09:08:11 XXXXXXXXXXXXX 1.1.1.1
09:09:03 YYYYYYYY 2.2.2.2
09:12:37 ZZZZ 3.3.3.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With