Search code examples
perlformatstring-formatting

Perl formatting a string


I'm trying to format a string which has three columns. The first column data length can be different so I don’t know how to format my string in a right way.

for my $k(keys %results) {
   my ($k1,$k2);
   # $k1 and $k2 are always equal to '-' or '+'
   # $k = "nnn_12_555_addd";
   ...
   format STDOUT =
@<<<<<<<<<< @> @>
$k, $k1, $k2
.
   write;
}

How do I make the first column @<<<< to keep the right size?

If the $k value is longer than the specified <'s, I'm losing a part from that value in the output...

Sample input

$k1 = '+'
$k2 = '-'

$k = 'aaa_bbb'
output:
aaa_bbb            +    -

$k = 'aaa_bbb_ccc'
output:
aaa_bbb_ccc        +    -

$k = 'aaa_bbb_ccc_ddd'
output:
aaa_bbb_ccc_ddd    +    -

Solution

  • I suggest you forget about Perl's format() and use printf() instead:

    use strict;
    use warnings 'all';
    
    my $k1 = '+';
    my $k2 = '-';
    
    for my $k (qw/ aaa_bbb  aaa_bbb_ccc  aaa_bbb_ccc_ddd /) {
        printf "%-20s%-5s%-5s\n", $k, $k1, $k2;
    }
    

    Output

    aaa_bbb             +    -
    aaa_bbb_ccc         +    -
    aaa_bbb_ccc_ddd     +    -
    


    Update

    If you want to fit the first column width to the longest of the values, you can use a dynamic field width in printf. A format specifier like %*s takes two values from the parameter list: an integer width for the fields and a string.

    The program would look like this:

    use strict;
    use warnings 'all';
    
    use List::Util 'max';
    
    my $k1 = '+';
    my $k2 = '-';
    
    my @k_vals = qw/ aaa_bbb  aaa_bbb_ccc  aaa_bbb_ccc_ddd  aaa_bbb_ccc_ddd_eee /;
    my $w = max map length, @k_vals;
    
    for my $k ( @k_vals ) {
        printf "%-*s %-5s%-5s\n", $w, $k, $k1, $k2;
    }
    

    Output

    aaa_bbb             +    -
    aaa_bbb_ccc         +    -
    aaa_bbb_ccc_ddd     +    -
    aaa_bbb_ccc_ddd_eee +    -