【问题标题】:Perl only executes part of shell command and emits warning 'redundant argument in printf' in command substitutionPerl 仅执行部分 shell 命令并在命令替换中发出警告“printf 中的冗余参数”
【发布时间】:2016-10-12 18:36:45
【问题描述】:

以下内容已在 OS X 10.11.5 上使用 perl 5.24 进行了测试。

我编写了一个短程序 (perl-embed.pl) 来确定 perl 在将字符串插入反引号时是否会转义 shell 元字符(它不会)。

use strict;
use warnings;

my $bar = '" ; echo 45 ; "';

printf "%s\n", `echo "hi${bar}ls"`;

我很惊讶地看到这会产生一个警告并且只执行了部分命令。

$ perl perl-embed.pl
Redundant argument in printf at perl-embed.pl line 6.
hi

为了比较以下程序 (perl-embed2.pl) 与 print 而不是 printf 运行时没有警告。

use strict;
use warnings;

my $bar = '" ; echo 45 ; "';

print `echo "hi${bar}ls"`;

然后我运行它。

$ perl perl-embed2.pl
hi
45
<contents of current working directory>

perl-embed.pl 的行为完全出乎意料。 printf 在其他上下文中插入字符串的内容也很好,即使字符串包含奇怪的字符。

$ perl -Mstrict -Mwarnings -e 'printf "%s\n", q[5]'
5

$ perl -Mstrict -Mwarnings -e 'printf "%s\n", q["]'
"

系统 perl(5.18 版)不会发出此警告,但似乎没有像我们预期的那样执行 ls 或 echo 45

$ /usr/bin/perl perl-embed.pl
hi

$ /usr/bin/perl perl-embed2.pl
hi
45
<contents of current directory>

为什么 perl 会这样?请注意,在每种情况下,perl 都会正常退出。

【问题讨论】:

    标签: perl


    【解决方案1】:

    您在列表上下文中使用反引号,所以表达式

    `echo "hi${bar}ls`
    

    将运行命令

     `echo "hi"; echo 45; ls`
    

    并在单独的元素中返回每一行输出,例如

    ( "hi",
      "45",
      "foo",
      ...     # other files in current directory
     )
    

    但是printf ("%s\n") 中的模板只有一个占位符,所以printf 会混淆并发出警告,就像你说的那样

    perl -we 'printf "%d\n", 1, 2, 3, 4'
    

    【讨论】:

    • 哦,我明白了。 printf "%s\n", (scalar `echo "hi"; echo 45; ls`); 实际上会有预期的行为。
    猜你喜欢
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2013-04-16
    • 2017-12-27
    • 2012-04-02
    相关资源
    最近更新 更多