How can I include a variable 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.
Printing Perl variables with print In any real-world Perl script you'll need to print the value of your Perl variables. To print a variable as part of a a string, just use the Perl printing syntax as shown in this example: $name = 'Alvin'; print "Hello, world, from $name.
Perl variables do not have to be explicitly declared to reserve memory space. The declaration happens automatically when you assign a value to a variable. The equal sign (=) is used to assign values to variables.
Meaning you can't declare a variable or function called printf at file scope, but you can do so at local scope. Now of course, people do declare macros called printf all the time for the purpose of "function mocking", so in practice it's harmless.
sprintf and printf sprintf is used to print in a formatted way. Suppose you have a variable having a value of 3.14159, then by using sprintf function you can control the precision of digits after decimal while printing. It means that you can print only 3.14. printf can be used instead of print sprintf.
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.
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