【问题标题】:How can I include a variable in a Perl printf expression?如何在 Perl printf 表达式中包含变量?
【发布时间】:2011-01-18 01:36:02
【问题描述】:

如何在 printf 表达式中包含变量?

这是我的例子:

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

其中$cols 是列数 而$_ 是一个字符串。

该语句导致“无效转换”警告。

问题最终是我忘记咀嚼变量了。嘎。谢谢大家。

【问题讨论】:

  • 能否请您发布完整的警告文本?
  • 我认为问题在于我从用户(STDIN)那里获取了列数。这是完整的错误: invalid conversion in printf: "%\012" at column2 line 28, line 3 (#1) (W printf) Perl 不理解给定的格式转换。参见 perfunc/sprintf。这是 $cols = 20。但它实际上可能是 $cols = "20"
  • 所以答案最终是我需要减少列数,因为它是来自 STDIN 的用户输入并且最后有一个换行符。
  • 当您遇到此类问题时,请查看您尝试使用的字符串,以确保它是您认为的那样:print "%${cols}s"。您的大部分编程时间可能会检查值以查看它们是否与您认为的一样。

标签: perl variables printf interpolation


【解决方案1】:

您的插值变量 $cols 看起来应该是一个数字,比如 10,所以

"%${cols}s"

应该插值并等价于

"%10s"

这是一个有效的格式字符串。

如果$cols 不是数字或有效格式字符串其他,您会收到警告。

例如,如果:

$cols = "w";

这将导致 "%ws" 作为格式字符串 - 给出您引用的错误:

Invalid conversion in printf: "%w"

可以在here找到有效的格式信息。

【讨论】:

  • +1 这是相关的,因为它正确显示了错误消息。我想我知道真正的问题是什么,但如果不听 OP 的话,就不可能知道。
【解决方案2】:

我发现了您的具体问题。你的代码是正确的。但是,我想$cols 可能是从用户输入中读取的数字,例如:

my $cols = <STDIN>;

这可行,在数字上下文中$cols 将显示为一个数字,但问题是$cols 没有出现在数字上下文中。它在字符串上下文中,这意味着您的格式字符串不是扩展为"%5s",而是扩展为"%5\ns"。那里的换行符弄乱了格式字符串。

将您阅读 $cols 的代码更改为:

chomp(my $cols = <STDIN>);

请参阅chomp 上的文档,因为您可能还想将其用于其他输入读取。

【讨论】:

  • 这就是答案。我在用户输入的末尾附加了一个新行,用户输入了列数。非常感谢! :)
【解决方案3】:

始终在格式说明符中使用* 以明确指示可变宽度!这类似于使用printf "%s", $str 而不是printf $str 的建议。

来自perlfunc documentation on sprintf

(最小)宽度

参数通常被格式化为显示给定值所需的宽度。您可以通过在此处输入数字来覆盖宽度,或者从下一个参数(使用*)或从指定的参数(使用例如*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)

如果通过*获得的字段宽度为负,则与-标志的效果相同:左对齐。

例如:

#! /usr/bin/perl

use warnings;
use strict;

my $cols = 10;
$_ = "foo!";
printf "%*s\n", $cols, $_;
print "0123456789\n";

输出:

 呸!
0123456789

启用warnings pragma 后,您将看到非数字宽度参数的警告。

【讨论】:

    【解决方案4】:

    你当前的方法应该可以工作

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

    【讨论】:

    • 您应该使用-Mstrict-Mwarnings 对其进行测试,但它确实有效。好奇为什么 OP 现在收到警告...
    • 我在发布之前做过;)我不希望它看起来像这个答案花了我超过 5 秒的时间。使用 Perl 测试这些东西真的很简单,我真的不需要删掉这些东西来把我的观点带回家。
    【解决方案5】:

    以下似乎对我有用:

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

    产量

    28$ ./test.pl
        3
    
    29$ 
    

    【讨论】:

      【解决方案6】:

      我无法重现您的问题。以下代码工作正常:

      use strict;
      use warnings;
      
      my $cols=40;
      while (<>) {
          printf "%${cols}s\n", $_;
      }
      

      它使用至少 40 列宽度打印任何输入行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-07
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 1970-01-01
        • 2012-06-16
        • 2011-07-05
        • 2017-01-14
        相关资源
        最近更新 更多