12

我刚刚开始使用 Perl(字面意思是今天),我正在阅读免费在线版本的Beginning Perl。早些时候,书中提到将插入双引号字符串。但是,在使用 print 函数的每个示例中(到目前为止......我在第 66 页左右),作者将标量变量作为列表参数传递。也许我是在抢先一步,这将在后面解释,但是有什么理由选择方法 A 而不是方法 B 吗?

方法一:

$myVar = "value";
print "Current value is ", $myVar, "\n";

方法B:

$myVar = "value";
print "Current value is $myVar\n";

在我看来,方法B更方便。社区中是否有首选方式?或者可能是一些隐藏的陷阱使一种方法比另一种方法更安全等等?

TIA

4

10 回答 10

14

肯定有隐藏的陷阱——perl 会处理简单的变量名,以及像这样的表达式

"$array[$subscript]"

"$hashref->{key}"

没有任何问题。但是,随着您的表达式变得越来越复杂,最终 perl 将无法判断您的表达式在哪里停止以及字符串的其余部分从哪里开始。

本文有很多血淋淋的细节双引号字符串中的变量插值(最初在这里,但现在下降)

于 2009-11-17T19:36:19.867 回答
12

插值有几件事情需要注意,尽管一旦你了解它们,你几乎不会误操作它们。

将变量名称放在有效标识符文本旁边。Perl 会找到最长的有效变量名,并且不关心它是否是先前定义的。您可以用大括号将变量名称部分设置为显式:

  my $p = 'p';
  print "Mind your $ps and qs\n";  # $ps, not $p

  print "Mind your ${p}s and qs";  # now its $p

现在,在那个例子中,我忘记了撇号。如果我添加它,我还有另一个问题,因为撇号曾经是过去的包分隔符,它仍然有效。大括号也在那里工作:

  my $p = 'p';
  print "Mind your $p's and q's\n";  # $p::s, not $p

  print "Mind your ${p}'s and q's";  # now its $p

Perl 还可以插入对散列和数组的单个元素访问,因此将索引字符放在变量名旁边可能会做一些你不想要的事情:

 print "The values are $string[$foo]\n";  That's the element at index $foo
 print "The values are $string{$foo}\n";  That's the value for the key $foo

当您想要一个字符串中的电子邮件地址时,您可能会忘记 Perl 插入数组。Perl 过去常常犯下致命错误,除非你转义了@

 print "Send me mail at joe@example.com\n";  # interpolates @example

 print "Send me mail at joe\@example.com\n";

由于 Perl 使用反斜杠来转义一些字符,所以当你想要一个字面值时,你需要将它们加倍:

 print "C:\real\tools\for\new\work";      # not what you might expect

 print "C:\\real\\tools\\for\\new\\work"; # kinda ugly, but that's life
 print "C:/real/tools/for/new/work";      # Windows still understands this

尽管有这些小问题,但如果我必须使用另一种语言,我真的很怀念在 Perl 中构建字符串的便利性。

于 2009-11-17T20:58:50.137 回答
12

'个问题:

$owner = "John";
$item = "motorcycle".
print "This is $owner's $item.\n";  # Oops, parsed as $owner::s

但上面可以安全地写成

print "This is ${owner}'s $item.\n";
于 2009-11-17T19:41:06.907 回答
12

在像这样的简单示例中,不。但考虑 if$myVar实际上是更复杂的东西,例如哈希引用的深度取消引用或方法调用。有些东西会在字符串中插入(大多数对象引用都会这样做),但方法调用不会。当直接打印出来与插入到字符串中时,数组也会做不同的事情。

PS。欢迎使用 Perl;请享受旅程!:)

于 2009-11-17T19:25:08.483 回答
4

方法A应该是:

$myVar = "value";
print 'Current value is ', $myVar, "\n";

当您单引号一个字符串时,Perl 不会费心阅读整个内容来寻找要插值的内容,因此如果您有一个不需要插值的长字符串,使用单引号并附加动态部分可能会更快,如上。

然而,这是一个微优化,并没有真正产生巨大的影响。

使用方法 A 的另一种情况是,如果字符串包含您不想转义的转义字符:

$myVar = 12000;
print 'Conversion from $US to $CND: ', $myVar,\n";

在这种情况下,您不希望 Perl 查找$USand$CND变量,您只希望字符串中包含美元符号。

最后,这主要是风格问题。我通常尽量避免使用双引号字符串,除非我需要它们。

于 2009-11-17T19:25:46.620 回答
3

因为我们正在讨论插值陷阱,所以值得一提的是,如果您使用单引号字符串来避免插值,您仍然需要转义尾部斜杠:

'c:\files\'  #parse error
'c:\files\\' #correct

这是因为第一个字符串的最后一个字符看起来像一个转义的单引号,而不是字符串终止符。转义的斜杠也将转换为单引号字符串中的单斜杠

于 2009-11-17T20:04:42.597 回答
2

如果您正在使用 Perl,那么您正在寻找完成工作的最快方法。此外,我们鼓励您以最符合您的思维方式的方式来做这件事(因此 Perl 的座右铭:TMTOWTDI,有不止一种方法)。因此:无论哪种方式对您来说更容易编写,无论哪种方式在您稍后回到代码时最有可能理解,都是您应该这样做的方式(所有其他事情,例如给出预期的结果,是平等的)。

如果您按照您的建议担心“安全”,那么请了解tainting,这有助于保护您免受来自外部世界的潜在恶作剧数据的侵害。

于 2009-11-17T19:23:55.680 回答
1

(这应该是社区 wiki。)

我想到的唯一明显的问题是数组的插值。相比

print @arr, "\n";

print "@arr\n";

此外,有时复杂的取消引用不适用于插值,但这种情况很少见。

于 2009-11-17T19:21:17.307 回答
0

作为一个不熟悉任何特定于 perl 的编辑器及其突出显示功能的 Perl 局外人,我投票赞成尽可能使用单引号。这使读者更清楚,该字符串不包含任何将以任何方式插入的内容。

于 2009-11-17T19:31:25.010 回答
0

插值是一个伟大的简化和节省时间。但也有可能走得太远。

如果你愿意,你可以用插值做一些奇怪的事情。

@foo = 0..10;
print "$foo[2*3]"; # prints 6

对于令人兴奋的任意插值,您可以使用这个可憎的:

print "@{[ some_function_call('in list context') ]}";

如果你真的,真的想让内插函数调用工作,有一个模块可以做到这一点。查看插值。它可以让你做这样的事情:

use Interpolation;
print "I like $eval{ what_I_like() };

sub what_like_like {
    return 'pie';
}

还有很多很多。

有关此模块的背景信息,请参阅Identity.pm:一个非常有趣的模块插值

于 2009-11-18T02:34:02.900 回答