How can I pad part of a string with spaces, in Perl?
Which version would you prefer?
#!/usr/bin/env perl
use warnings;
use strict;
use 5.010;
my $p = 7; # 33
my $prompt = ' : ';
my $key = 'very important text';
my $value = 'Hello, World!';
my $length = length $key . $prompt;
$p -= $length;
Option 1:
$key = $key . ' ' x $p . $prompt;
Option 2:
if ( $p > 0 ) {
$key = $key . ' ' x $p . $prompt;
}
else {
$key 开发者_如何学运维= $key . $prompt;
}
say "$key$value"
I would prefer
sprintf "%-7s : %s", $key, $value;
or
sprintf "%-*s : %s", $p, $key, $value;
instead of all this weird stuff.
From the sprintf
documentation:
The flag characters
'-'
The converted value is to be left adjusted on the field boundary. (The default is right justification.) The converted value is padded on the right with blanks, rather than on the left with blanks or zeros. A'-'
overrides a0
if both are given.The field width
An optional decimal digit string (with nonzero first digit) specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given). Instead of a decimal digit string one may write
'*'
or'*m$'
(for some decimal integerm
) to specify that the field width is given in the next argument, or in the m-th argument, respectively, which must be of type int. A negative field width is taken as a'-'
flag followed by a positive field width. In no case does a nonexistent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.
I don't like option 2 as it introduces an unnecessary special case.
I would refactor out the construction of the prompt suffix:
# Possible at top of program
my $suffix = ( ' ' x $p ) . $prompt;
# Later...
$key .= $suffix ;
Call me old-school, but I'd use printf() or sprintf():
printf "%-33s%s%s\n", $key, $prompt, $value;
That left justifies the string $key into 33 spaces, adds $prompt and $value and a newline. If I wanted to calculate the length for the first part dynamically:
printf "%-*s%s%s\n", $len, $key, $prompt, $value;
Since it is one line instead of the question's 4 (option 1) or 6 (option 2), it scores favourably on the succinctness scale.
I looks a little weird, but this works (until now):
#!/usr/bin/env perl
use warnings; use strict;
use 5.010;
use utf8;
use Term::Size;
my $columns = ( Term::Size::chars *STDOUT{IO} )[0];
binmode STDOUT, ':encoding(UTF-8)';
use Text::Wrap;
use Term::ANSIColor;
sub my_print {
my( $key, $value, $prompt, $color, $p ) = @_;
my $length = length $key.$prompt;
$p -= $length;
my $suff = ( ' ' x $p ) . $prompt;
$key .= $suff;
$length = length $key;
my $col = $columns - $length;
$Text::Wrap::columns = $col;
my @array = split /\n/, wrap ( '','', $value ) ;
$array[0] = colored( $key, $color ) . $array[0];
for my $idx ( 1..$#array ) {
$array[$idx] = ( ' ' x $length ) . $array[$idx];
}
say for @array;
}
my $prompt = ' : ';
my $color = 'magenta';
my $p = 30;
my $key = 'very important text';
my $value = 'text ' x 40;
my_print( $key, $value, $prompt, $color, $p );
精彩评论