my @a = (1,2,3,4,5);
print @a; #output: 12345
print "\n";
print "@a"; #output: 1 2 3 4 5
通过将名称加上双引号来打印数组会在输出的每个索引值之间放置一个空格。它是如何做到的?为什么print @a;
打印不一样?两种类型的需求是什么?我的意思是你什么时候使用print @a;
而不是print "@a";
,反之亦然。
更好的问题:为什么不打印类似数组{0x1232ef}的东西。打印是假设打印字符串输出而@a
不是标量。
哎呀,甚至更好:这是一个标量上下文,所以为什么不打印5
,这是数组中元素的数量。这是如何:
print scalar @a;
会打印。
相反,print
命令正在采取一些自由来尝试做你想要的而不是你所说的你想要的。
我们来看看这个小程序:
@a = qw(a b c d e);
print "@a"; #prints "a b c d e"
print "\n";
print @a; #prints "abcde"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
请注意,print @a
打印abcde
,但如果我在最后添加\n
,它会在标量上下文中打印@a
。
看看Perldoc on print(尝试命令perldoc -f print
。在大多数系统上,整个Perl文档可以通过perldoc
获得)
* print LIST
* print
Prints a string or a list of strings. Returns true if successful[...]
啊!如果给出一个列表,它将打印一个字符串列表。
在每个LIST项目之间打印$(如果有)的当前值。在打印完整个LIST后打印$ \(如果有)的当前值。因为print采用LIST,所以LIST中的任何内容都在列表上下文中进行评估,包括您传递给打印的返回列表的所有子例程。
我们来试试一个新程序:
@a = qw(a b c d e);
$, = "--";
print "@a"; #prints "a b c d e"
print "\n";
print @a; #prints "a--b--c--d--e"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
嗯...... $,
在列表元素之间添加了双短划线,但它并没有影响引号中的@a
。而且,如果在$,
中提及perldoc
,为什么每个人都在讨论$"
?
我们来看看perldoc perlvar
* $LIST_SEPARATOR
* $"
When an array or an array slice is interpolated into a double-quoted string or a
similar context such as /.../ , its elements are separated by this value. Default
is a space. For example, this:
print "The array is: @array\n";
is equivalent to this:
print "The array is: " . join($", @array) . "\n";
Mnemonic: works in double-quoted context.
所以,这解释了一切!
$"
的默认值是单个空格,$,
的默认值为null。这就是为什么我们得到了我们得到的东西!
还有一个程序......
@a = qw(a b c d e);
$, = "--";
$" = "++";
print "@a"; #prints "a++b++c++d++e"
print "\n";
print @a; #prints "a--b--c--d--e"
print "\n";
print @a . "\n"; #prints "5"
print scalar @a; #prints "5"
在第一个实例中,您将一个参数列表传递给print
,并依次打印每个参数。
在第二个中,您将数组插入到字符串中,然后打印结果。当一个数组以字符串插值时,这些值由$"
分隔,默认为。
当Perl在插值字符串中看到一个数组时,它会使用join重写它:
print "@array";
变
print join($" => @array);
默认情况下,$"
的值等于单个空格。
您可以通过将更改本地化为$"
来配置此行为
print "@array"; # '1 2 3 4 5'
{
local $" = ''; # "
print "@array"; # '12345'
}
print "@array"; # '1 2 3 4 5'
你可以看到Perl如何使用核心-q
模块的B::Deparse
选项重写插值字符串:
$ perl -MO=Deparse,-q -e 'print "@array"'
print join($", @array);
-e syntax OK
“Array Interpolation” section of the perldata documentation解释了"@a"
值的插入空间如何到达:
通过将元素与
$"
变量($LIST_SEPARATOR
,如果指定了use English;
)中指定的分隔符连接,将数组和切片插入到双引号字符串中,默认为空格。以下是等效的:$temp = join($", @ARGV); # " for benefit of StackOverflow hiliter system "echo $temp"; system "echo @ARGV";
这意味着print "@a"
将单个标量参数传递给print
。相比之下,你的例子中的print @a
传递了五个。
perlfunc documentation on print
用一系列论点解释了什么print
。
print LIST
...在每个LIST项目之间打印
$,
(如果有)的当前值。
Handle->output_field_separator( EXPR )
$OUTPUT_FIELD_SEPARATOR
$OFS
$,
打印操作员的输出字段分隔符。如果已定义,则在每个print参数之间打印此值。默认是
undef
。助记符:当你的
,
声明中有
因为$,
默认为未定义的值,所以你看到print
输出的参数没有分隔符。明确地说,您问题中的代码等同于
print join("", @a);
行为的差异不是print
的特例。数组内插到所有双引号字符串as described above中。对Google code-search hits for print "@...
的快速调查似乎表明print "@foo"
的频繁使用是调试输出,如
sub foo {
print "args = @_\n" if $debug;
...;
}
Mark Dominus用于为值可能包含空格的列表提供可见分隔符的方便技巧是
sub foo {
if ($debug) {
local $" = "][";
print "args = [@_]; # e.g., [foo][1][3.14159]
}
...;
}
假设@a
包含输出行,例如
@a = map " - $_\n", @error_messages;
print @a;
在值之间插入隐式空格会使我精心构造的格式化:
- sneaky-sneaky, sir - the hideousness of that foot will haunt my dreams forever - why would you do that?!
Perl努力做到我们的意思,即使我们的要求不一致。