用“连接”连接Perl中的字符串

时间:2010-11-18 16:48:52

标签: perl

请参阅下面的更新

我正在阅读我公司的某些人编写的一大堆Perl脚本。他使用join来连接字符串。例如,他这样做(从真正的Perl脚本中取出来):

$fullpath=join "", $Upload_Loc, "/", "$filename";

而不是:

$fullpath = "$Upload_Loc" . "/" . "$filename";

或者就是这样:

$fullpath = "$Upload_Loc/$filename";

他已经不在了,但是在这里的人告诉我他以这种方式连接字符串,因为它在某种程度上更好。 (他们不太清楚为什么)。

那么,为什么有人在使用join连接运算符时使用.,或者只是像第三个例子那样键入字符串?这种编码风格是否有正当理由?

我正在努力清理这里的许多烂摊子,我的第一个想法是结束这种做法。它使代码更难阅读,我确信做join不是一种连接字符串的非常有效的方法。然而,虽然自从3.x版以来我一直在用Perl编写脚本,但我并不认为自己是一个大师,因为我从来没有机会和Perl比Perl更好的人和我教我Perl深刻的内心秘密。在我自欺欺人之前,我只是想确保我的直觉在这里是正确的。

我有更好的方法在这里做到这一点。


更新

人们感到困惑。他不只是为了连接路径。这是另一个例子:

$hotfix=join "", "$app", "_", "$mod", "_", "$bld", "_", "$hf", ".zip";

我会在哪里做这样的事情:

$hotfix = $app . "_"  $mod . "_" . $bld . "_" . "$hf.zip";

或者,更有可能

$hotfix = "${app}_${mod}_${bld}_${hf}.zip";

或许在这种情况下,我可能实际使用join,因为下划线会导致问题:

$hotfix = join("_", $app, $mod, $bld, $hf) . ".zip";

我的问题仍然是:他是否正在做一些真正的Perl黑客知道的事情,而像我一样只做了15年的新手却不知道?人们会看着我使用.连接字符串,或者只是将它们放在引号中并说“哈!真是个菜!我打赌他也拥有一台Macintosh!”

或者,前一个人是否只有一个独特风格的编程,就像我儿子的独特风格的驾驶包括跑进树林一样?

7 个答案:

答案 0 :(得分:6)

我为“一个知名的在线零售商”做了我公平的商业Perl开发,我从来没有见过join这样的用法。你的第三个例子是我的首选,因为它简单,干净,易读。

与其他人一样,我认为使用join作为性能增强器并没有任何真正的价值。它可能比字符串插值更好地执行,但我无法想象一个真实的情况,其中优化可能是合理的,但代码仍然用脚本语言编写。

正如这个问题所表明的那样,深奥的编程习语(用任何语言)只会导致很多误解。如果你很幸运,这种误解是良性的。我喜欢和他们一起工作的开发人员是编写可读性和一致性的代码,并在周末离开Perl Golf。 :)

简而言之:是的,我认为他独特的风格类似于你儿子独特的驾驶风格。 :)

答案 1 :(得分:4)

我会考虑

$fullpath = join "/", $Upload_Loc, $filename;

比替代品更清晰。但是,File::Spec已经成为核心很长一段时间了,所以

use File::Spec::Functions qw( catfile );
# ...
$fullpath = catfile $Upload_Loc, $filename;

好多了。而且,更好的是,有Path::Class

use Path::Class;

my $fullpath = file($Upload_Loc, $filename);

在连接文件名和路径时,速度通常不是我考虑的因素。

您在更新中提供的示例:

$hotfix=join "", "$app", "_", "$mod", "_", "$bld", "_", "$hf", ".zip";

说明了为什么这个家伙一无所知。首先,不需要插入那些单独的变量。其次,这更好地写成

$hotfix = join '_', $app, $mod, $bld, "$hf.zip";

或者,作为

$hotfix = sprintf '%s_%s_%s_%s.zip', $app, $mod, $bld, $hf;
减少不必要的标点符号是我的最终目标。

答案 2 :(得分:3)

通常,除非要加入的项目列表很大,否则您将看不到很多性能差异,将它们更改为连接。主要关注的是可读性和可维护性,在这种情况下,如果字符串插值形式更清晰,您当然可以使用它。

我猜这只是原始程序员的个人编码偏好。

一般情况下,当列表的长度很大/未知时,或者我正在使用空字符串以外的其他内容(或用于数组插值的单个空格)时,我会使用join。否则,使用.或简单的字符串插值通常更短,更容易阅读。

答案 3 :(得分:2)

Perl将双引号字符串编译成包含join.个字符串的内容:

$ perl -MO=Deparse,-q -e '$fullpath = "$Upload_Loc/$filename"'
$fullpath = $Upload_Loc . '/' . $filename;
-e syntax OK

$ perl -MO=Deparse,-q -le 'print "Got @ARGV"'
BEGIN { $/ = "\n"; $\ = "\n"; }
print 'Got ' . join($", @ARGV);
-e syntax OK

这可能会激发你这样的事情:

$rx = do { local $" = "|"; qr{^(?:@args)$} };

如:

$ perl -le 'print $rx = do { local $" = "\t|\n\t"; qr{ ^ (?xis: @ARGV ) $ }mx }' good stuff goes here
(?^mx: ^ (?xis: good    |
        stuff   |
        goes    |
        here ) $ )

Nifty,是吗?

答案 4 :(得分:1)

插值比加入列表慢一点。那说我从来不认识任何人把它带到这个极端。

您可以使用Benchmark模块来确定存在多大差异。

另外,您可以在http://perlmonks.org/上提出这个问题。那里有真正的大师可能会比我更好地给你内心的秘密。

答案 5 :(得分:0)

所有这些方法都很好。

Join有时可能比. concatentate更强大,特别是当您加入的某些内容是数组时:

join "/", "~", @document_path_elements, $myDocument;

答案 6 :(得分:0)

虽然认识到在我看到的所有示例中都没有明显的性能差异,但是无论是.还是双引号插值,一系列连接确实会比内存效率低得多。一个join,它为结果预先计算所需的字符串缓冲区,而不是多次展开它(甚至可能需要每次都将部分resutl移动到一个新位置)。

我在这里看到的批评有问题;有很多正确的方式可以说perl,这肯定是其中之一。

另一方面,压痕不一致......