Perl 中的插值有什么缺点吗?

发布于 2024-08-11 09:39:07 字数 516 浏览 5 评论 0原文

我刚刚开始使用 Perl(字面意义上的今天),并且正在阅读免费的在线版本 开始 Perl。早些时候,这本书提到双引号字符串将被插入。然而,在每个使用 print 函数的示例中(到目前为止......我在第 66 页左右),作者将标量变量作为列表参数传递。也许我有点操之过急,稍后会对此进行解释,但是有什么理由选择方法 A 而不是方法 B?

方法A:

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

方法B:

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

我认为,方法B更方便。社区里有首选的方式吗?或者也许有一些隐藏的陷阱使一种方法比另一种方法使用起来更安全等等?

TIA

I'm just starting out with Perl (literally today) and I'm reading the free online version of Beginning Perl. Early on, the book mentioned that double quoted strings will be interpolated. However, in every example using the print function (so far... I'm around page 66), the author is passing scalar variables as a list parameter. Maybe I'm jumping the gun and this will be explained later, but is there any reason to choose method A over method B?

Method A:

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

Method B:

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

In my opinion, method B is more convenient. Is there a preferred way in the community? Or maybe some hidden gotchas that make one method safer to use over the other etc.?

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

时光瘦了 2024-08-18 09:39:07

肯定有隐藏的陷阱——perl 将处理简单的变量名,以及类似

"$array[$subscript]"

and

"$hashref->{key}"

的表达式,没有任何问题。然而,随着表达式变得越来越复杂,最终 Perl 将无法分辨表达式在哪里停止以及字符串的其余部分开始。

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

There definitely are hidden gotchas -- perl will deal with simple variable names, and expressions like

"$array[$subscript]"

and

"$hashref->{key}"

without any problems. As your expressions get more and more complicated, though, eventually perl will not be able to tell where your expression stops and the remainder of your string starts.

There are lots of gory details in this paper Variable Interpolation in Double-Quoted Strings (originally here, but down now)

忱杏 2024-08-18 09:39:07

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

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

In a simple example such as this, no.. but consider if $myVar was actually something more complicated, such as a deep dereferencing of a hash reference, or a method call. Some things interpolate inside strings (most object references do), but method calls don't. Also arrays do different things when printed out directly vs. interpolated into a string.

PS. Welcome to Perl; please enjoy the journey! :)

姜生凉生 2024-08-18 09:39:07

这里有 ' 问题:

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

但是上面的内容可以安全地写成

print "This is ${owner}'s $item.\n";

There's the ' gotcha:

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

but the above can be safely written as

print "This is ${owner}'s $item.\n";
-小熊_ 2024-08-18 09:39:07

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

将变量名称放在有效标识符文本旁边。 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 [email protected]\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 中构造字符串的轻松程度。

There are several things to watch out for with interpolation, although once you know about them, you hardly ever do them by mistake.

Putting a variable name next to valid identifier text. Perl finds the longest valid variable name and doesn't care if it is previously defined. You can set off the variable name portion with braces to be explicit:

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

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

Now, in that example, I forgot the apostrophe. If I add it, I have another problem since the apostrophe used to be the package separator from the old days and it still works. The braces work there too:

  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 can also interpolate single element accesses to hashes and arrays, so putting indexing characters next to a variable name might do something you don't want:

 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

When you want an email address in a string, you might forget Perl interpolates arrays. Perl used to make that a fatal error unless you escaped the @:

 print "Send me mail at [email protected]\n";  # interpolates @example

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

Since Perl uses the backslash to escape some characters, you need to double up those when you want a literal one:

 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

Despite these minor gotchas, I really miss the ease with which I can construct strings in Perl if I have to use another language.

萧瑟寒风 2024-08-18 09:39:07

方法 A 应该是:

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

当你单引号一个字符串时,Perl 不会费心去读取整个字符串来寻找要插值的内容,所以如果你有一个不需要插值的长字符串,那么使用单引号可能会更快并附加动态部分,如上所示。

然而,这是一个微观优化,并不会真正产生巨大的差异。

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

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

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

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

Method A should be:

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

When you single-quote a string, Perl doesn't bother reading the whole thing looking for things to interpolate, so if you have a long string that doesn't need interpolation, it may be faster to use single quotes and append the dynamic parts, like above.

However, this is a micro-optimization that doesn't really make a huge difference.

Another case for using Method A is if the string contains escape characters that you don't want to bother escaping:

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

In this case, you don't want Perl to look for the $US and $CND variables, you just want the string to have the dollar sign in it.

In the end, it's mostly a matter of style. I usually try to avoid double-quoted strings unless I need them.

硪扪都還晓 2024-08-18 09:39:07

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

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

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

since we are talking about interpolation gotchas, its worth mentioning that if you are using single quoted strings to avoid interpolation, you still will need to escape a trailing slash:

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

this is because the final character of the first string looks like an escaped single quote, rather than the string terminator. also an escaped slash will be converted to a single slash in single quoted strings

牵你手 2024-08-18 09:39:07

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

如果您像您建议的那样担心“安全”,那么请了解污染,这有助于保护您免受来自外部世界的潜在恶作剧数据的影响。

If you're reaching for Perl, then you're looking for the quickest way to get things done. You are, furthermore, encouraged to do it in the way that is most like your way of thinking (hence the Perl motto: TMTOWTDI, There's More Than One Way To Do It). Therefore: whichever way is easier for you to write, whichever way you're most likely to understand when you come back to the code later, is the way you should do it (all other things, such as giving the intended result, being equal).

If you're concerned about "safety", as you suggest, then learn about tainting, which helps protect you from potentially mischievous data from the outside world.

不交电费瞎发啥光 2024-08-18 09:39:07

(这可能应该是社区维基。)

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

print @arr, "\n";

print "@arr\n";

,有时复杂的取消引用不能很好地与插值一起使用,但这种情况很少见。

(This should probably be community wiki.)

The only obvious issue that comes to my mind is the interpolation of arrays. Compare

print @arr, "\n";

with

print "@arr\n";

Also, sometimes complicated dereferencing don't work well with interpolation, but those are kind of rare.

老旧海报 2024-08-18 09:39:07

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

As a Perl outsider who is not familiar with any perl-specific editors and their highlighting powers, I vote for using single quotes whenever possible. This makes it clearer to the reader, that this string contains nothing that will be interpolated in any way.

┾廆蒐ゝ 2024-08-18 09:39:07

插值法可以极大地简化程序并节省时间。但也有可能走得太远。

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

@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:一个非常有趣的模块插值

Interpolation is a great simplifier and time saver. But it is possible to go too far.

You can do some bizarre stuff with interpolation if you want to.

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

And for exciting arbitrary interpolation you can use this abomination:

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

If you really, really want to make interpolated function calls work, there is a module for that. Check out Interpolation. It lets you do stuff like this:

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

sub what_like_like {
    return 'pie';
}

And much, much more.

For background on this module, see Identity.pm: A Very Funny Module and Interpolation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文