How to centrally justify in printf function in Perl
I know the printf
function by default uses right-justification. -
will make it left justify. But is it possible to make it centrally ju开发者_开发知识库stify the format?
The printf
function cannot center text.
However, there is a very old, and almost forgotten mechanism that can do this. You can create format statements in Perl that tells write statements how to print. By using format and write, you can center justify text.
This was something sort of done back in the days of Perl 3.x back in 1989, but sort of abandoned by the time Perl 4 came out. Perl 5, with its stronger variable scoping really put a crimp in the use of formats since using them would violate the way Perl 5 likes to scope variables (formats are global in nature).
You can learn more about it by looking at perldoc perlform
. I haven't seen them used in years.
my @lines = (
"It is true that printf and sprintf",
"do not have a conversion to center-justify text.",
"However, you can achieve the same effect",
"by padding left-justified text",
"with an appropriate number of spaces."
);
my $max_length = 0;
foreach my $line (@lines) {
$max_length = (length $line > $max_length) ? length $line : $max_length;
}
foreach my $line (@lines) {
printf "%s%-${max_length}s\n", ' ' x int(($max_length - length $line)/2), $line;
}
You need to use two variables for each value you'd like to print and dynamically set the width of each around the value width. The problem becomes a little trickier if you want consistent total widths when your value has an odd/even string length. The following seems to do the trick!
use POSIX;
printf( "<%*s%*s>\n",
((10+length($_))/2), $_,
ceil((10-length($_))/2), "" )
for( qw( four five5 six666 7seven7 ) );
which prints
< four >
< five5 >
< six666 >
< 7seven7 >
You need to know the line width
for this. For example, printing centered lines to the terminal:
perl -lne 'BEGIN {$cols=`tput cols`} print " " x (($cols-length)/2),$_;' /etc/passwd
Of course, this is not a printf
formatting tag.
my @lines = (
"Some example lines",
"of differing length",
"to show a different approach",
"that actually",
"prints your content",
"centered in its max-width block",
"with minimal padding",
"(which the answer",
"by Sam Choukri does NOT do)."
);
# Get the required field width
my $max_length = 0;
foreach my $line ( @lines )
{
$max_length = length( $line ) if ( length( $line ) > $max_length );
}
foreach my $line ( @lines )
{
# First step, find out how much padding is required
my $padding = $max_length - length( $line );
# Get half that amount (rounded up) in spaces
$padding = ( ' ' x ( ( $padding + $padding % 2 ) / 2 ) );
# Print your output, with padding appended, right-justified to
# a max-width field.
# (Pipe character added to show that trailing padding is correct)
printf "%${max_length}s|\n", $line . $padding;
}
精彩评论