以下两个简单的perl程序有不同的行为:
#file1
printf @ARGV;
#file2
$tmp = sprintf @ARGV;
print $tmp;
$> perl file1 "hi %04d %.2f" 5 7.12345
#output: hi 0005 7.12
$> perl file2 "hi %04d %.2f" 5 7.12345
#output: 3
为什么会有区别?我原以为这两个程序是等价的。想知道是否有办法让file2(使用" sprintf")表现得像file1。
答案 0 :(得分:8)
内置sprintf
函数有一个原型:
$ perl -e 'print prototype("CORE::sprintf")'
$@
它将第一个参数视为标量。由于您提供了参数@ARGV
,因此通过传递@ARGV
中的元素数量将其强制转换为标量。
由于printf
函数必须支持语法printf HANDLE TEMPLATE,LIST
以及printf TEMPLATE,LIST
,因此它不支持原型。因此它始终将其参数视为一个平面列表,并使用列表中的第一个元素作为模板。
使第二个脚本正常工作的一种方法是将其称为
$tmp = sprintf shift @ARGV, @ARGV
printf
和sprintf
之间的另一个区别是print sprintf
会将$\
附加到输出,而printf
则不会(感谢,ysth)。
答案 1 :(得分:4)
@ARGV
包含以列表形式传递给脚本的参数。 printf
获取该列表并按原样打印出来。
在第二个示例中,您将sprintf
与数组一起使用并将其指定给标量。这基本上意味着它在变量$tmp
中存储数组的长度。因此,您获得3
作为输出。
答案 2 :(得分:3)
来自perl docs(jaypal已经说过)
与printf不同,当你传递一个数组作为你的第一个参数时,sprintf不会做你可能想要做的事情。数组给出了标量上下文,而不是使用数组的第0个元素作为格式,Perl将使用数组中元素的数量作为格式,这几乎从来没用过。