Perl只执行shell命令的一部分,并在printf'中发出警告'冗余参数。在命令替换中

时间:2016-06-12 05:58:23

标签: perl

在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都会正常退出。

1 个答案:

答案 0 :(得分:2)

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

`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'