How can I include a variable in a Perl printf expression?
How can I include a variabl开发者_StackOverflowe in a printf expression?
Here's my example:
printf "%${cols}s", $_;
Where $cols
is the number of columns
and $_
is a string.
The statement results in an "Invalid conversion" warning.
The problem ended up being that I forgot to chomp the variable. Gah. Thanks everyone.
Your interpolated variable $cols
looks like its supposed to be a number, say 10, so
"%${cols}s"
should interpolate and be equivalent to
"%10s"
which is a valid format string.
If however $cols
was something other than a number or valid format string, you'd get the warning.
For example, if:
$cols = "w";
that would result in "%ws"
as a format string - giving the error you quote:
Invalid conversion in printf: "%w"
Valid format information can be found here.
I figured out your specific problem. Your code is correct. However, I suppose $cols
might be a number read from user input, say like this:
my $cols = <STDIN>;
This works, and in numeric context $cols
will appear to be a number, but the problem is that $cols
isn't appearing in numeric context here. It's in string context, which means that instead of expanding to "%5s"
, your format string expands to "%5\ns"
. The newline there is mucking up the format string.
Change the code where you read $cols
to this:
chomp(my $cols = <STDIN>);
See the documentation on chomp
, as you may want to use it for other input reading as well.
Always use *
in your format specifier to unambiguously indicate variable width! This is similar to the advice to use printf "%s", $str
rather than printf $str
.
From the perlfunc documentation on sprintf
:
(minimum) width
Arguments are usually formatted to be only as wide as required to display the given value. You can override the width by putting a number here, or get the width from the next argument (with
*
) or from a specified argument (with e.g.*2$
):printf '<%s>', "a"; # prints "<a>" printf '<%6s>', "a"; # prints "< a>" printf '<%*s>', 6, "a"; # prints "< a>" printf '<%*2$s>', "a", 6; # prints "< a>" printf '<%2s>', "long"; # prints "<long>" (does not truncate)
If a field width obtained through
*
is negative, it has the same effect as the-
flag: left-justification.
For example:
#! /usr/bin/perl
use warnings;
use strict;
my $cols = 10;
$_ = "foo!";
printf "%*s\n", $cols, $_;
print "0123456789\n";
Output:
foo! 0123456789
With the warnings
pragma enabled, you'll see warnings for non-numeric width arguments.
Your current method should work
perl -e'my $cols=500; $_="foo"; printf "%${cols}s\n\n", $_;'
The following seems to work for me:
#!/bin/perl5.8 -w
use strict;
my $cols = 5;
my $a = "3";
printf "%${cols}d\n", $a;
yields
28$ ./test.pl
3
29$
I cannot reproduce your problem. The following code works fine:
use strict;
use warnings;
my $cols=40;
while (<>) {
printf "%${cols}s\n", $_;
}
It prints any input line using at least 40 columns of width.
精彩评论