How to include a variable in printf expression for Perl?

How to include a variable in printf expression?

Here is my example:

printf "%${cols}s", $_; 

Where $cols is the number of columns and $_ is the string.

The message "Invalid conversion" appears as a result of the message.

The problem ended up forgetting to split the variable. Gah. Thanks to everyone.

+7
variables perl printf interpolation
source share
6 answers

I understood your specific problem. Your code is correct. However, I believe that $cols may be a number read from user input, for example:

 my $cols = <STDIN>; 

This works, and in a numeric context $cols will display as a number, but the problem is that $cols does not appear here in a numeric context. This is in the context of the string, which means that instead of expanding to "%5s" your format string is expanding to "%5\ns" . In a newline, the formatting line is offset.

Change the code in which you read $cols :

 chomp(my $cols = <STDIN>); 

See the chomp documentation as you can use it for other introductory readings.

+9
source share

Your $cols interpolated variable looks like its number, for example, 10, so

 "%${cols}s" 

must interpolate and be equivalent

 "%10s" 

which is a valid format string.

If, however, $cols was anything other than a numeric or valid format, you will receive a warning.

For example, if:

 $cols = "w"; 

which will cause "%ws" be used as a format string, indicating the error you specified:

 Invalid conversion in printf: "%w" 

Information on the current format can be found here .

+11
source share

Always use * in the format specifier to uniquely indicate a variable width! This is similar to the recommendation to use printf "%s", $str , rather than printf $str .

From the perlfunc documentation on sprintf :

(minimum) width

Arguments are usually formatted as necessary to display this value. You can override the width by putting a number here or get the width from the following argument (using * ) or from the specified argument (for example *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 the width of the field obtained through * is negative, it has the same effect as the - flag: left alignment.

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 warnings you will see warnings for non-numeric width arguments.

+6
source share

Your current method should work

 perl -e'my $cols=500; $_="foo"; printf "%${cols}s\n\n", $_;' 
+3
source share

It seems to me that the following works:

 #!/bin/perl5.8 -w use strict; my $cols = 5; my $a = "3"; printf "%${cols}d\n", $a; 

gives

 28$ ./test.pl 3 29$ 
+1
source share

I can not 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.

+1
source share

All Articles