Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I include a variable in a Perl printf expression?

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.

like image 994
Lou Avatar asked Feb 17 '10 20:02

Lou


People also ask

How do I print a variable value in Perl script?

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.

How do I declare a variable in Perl?

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.

Can printf be used as a variable?

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.

How do I print an integer in Perl?

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.


3 Answers

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.

like image 199
martin clayton Avatar answered Nov 03 '22 01:11

martin clayton


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.

like image 22
Chris Lutz Avatar answered Nov 03 '22 00:11

Chris Lutz


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.

like image 27
Greg Bacon Avatar answered Nov 03 '22 00:11

Greg Bacon