开发者

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

开发者 https://www.devze.com 2022-12-20 06:53 出处:网络
How can I include a variabl开发者_StackOverflowe in a printf expression? Here\'s my example: printf \"%${cols}s\", $_;

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消