在Perl脚本中,我们应该使用shell命令还是调用模仿shell操作的Perl函数



我想了解这里的最佳实践。假设我想获取文件某行的内容。我可以使用一行shell命令来获得答案,或者编写一个子例程,如下面的代码所示。

一个名为some_text:的文本文件

She laughed. Then both continued eating in silence, like strangers,
but after dinner they walked side by side; and there sprang up
between them the light jesting conversation of people who are free
and satisfied, to whom it does not matter where they go or what
they talk about.

获取文件第5行内容的代码

#!perl
use warnings;
use strict;
my $file = "some_text";
my $lnum = 5;
my $shellcmd = "awk 'NR==$lnum' $file";
print qx($shellcmd);
print getSrcLine($file, $lnum);
sub getSrcLine {
    my($file, $lnum) = @_;
    open FILE, $file or die "$!";
    my @ray = <FILE>;
    return $ray[$lnum-1];
}

我之所以这么问,是因为我看到很多Perl脚本,在某些时候,会调用shell命令,而在稍后的某个时候,同样的任务是通过调用(库或手写)函数来完成的,例如,rm -rfFile::Path::rmtree。我只是想让它保持一致。

建议做什么?

如果操作有Perl函数,Perl认为您应该使用它的版本。然而,您给出了一个Perl模块的例子,它提供了一种纯Perl的方法来实现这一点。没有单一的答案(就像大多数事情一样),所以你必须自己决定该做什么:

  • 纯Perl方法正确吗?例如,File::Copy有一些局限性,因为它为用户做出了一些尴尬的决定,所以很多人认为它坏了。例如,请参见文件::复制与cp/mv。

  • 纯Perl方法能在可接受的时间内完成吗?有时外部程序的速度要快几个数量级。有时会慢很多。

  • 外部命令通常在一系列系统(例如,所有类似linux的系统)中是可移植的,但可能不会跨系列(例如,Windows和linux)。你对此的容忍度可能会影响你的回答。即使您认为您在运行相同的命令,不同风格的类unix系统也可能有不同的操作开关。

  • 将复杂的参数——空格、引号和特殊字符——传递给外部命令可能会让你哭。你必须做很多繁琐的工作来确保你正确地处理论点。Perl子例程并不在意。

  • 当你使用外部命令时,你必须更加注意你在做什么。如果您只调用rm,Perl将搜索您的PATH并使用第一个名为rm的东西。这并不意味着它就是你认为的程序。我在MasteringPerl中的"安全编程技术"中写了很多关于这一点的文章。

  • 如果纯Perl方法需要一个模块,特别是如果该模块有许多复杂的依赖关系,那么您可能会面临依赖关系或分布问题。

就我个人而言,我从纯Perl方法开始,直到它不适用于这种情况。

对于您的特定示例,我将使用Perl。将外壳扩展到awk,这是一个原型Perl,这很奇怪。您应该能够做awk做的一切正确的Perl。如果您有一个awk程序,您可以使用a2p程序将其转换为Perl:

 NR==5

a2p将其转换为(在开始时模化一些设置位):

while (<>) {
    print $_ if $. == 5;
}

请注意,即使您有第五行,它仍然会扫描整个文件。但是,您可以使用翻译后的程序作为开始:

while (<>) {
    if( $. == 5 ) {
        print;
        last;
        }
}

我认为您不应该为了避免使用Perl代码而使用其他程序。

要删除目录树,我喜欢File::Path。它有一些依赖项,但它们都在Perl标准库中。这个模块几乎没有什么痛苦,如果有的话。我会一直使用它,直到遇到问题,它不起作用。

如果您希望您的应用程序可移植到非unix系统,那么一定要用Perl编写所有内容。

如果没有,那真的取决于你。。。创建一个新流程的速度较慢,但如果它对任务不重要,那么也没关系。就我个人而言,我会选择可以更快实施的解决方案。

在我看来,工作的代码应该是第一要务。例如,如果文件名中有空格,则您的操作将失败。

由于您的程序需要正确生成另一个由sh运行的程序,因此使用shell会使正确编码变得更加困难。(如果你使用多参数版本的系统来避免外壳,这个问题就会消失。)

此外,使用外部工具会使处理错误变得困难。你甚至都没试着这么做!

另一方面,使用外部工具有多种原因。例如,Perl提供的文件复制实用程序不如cp好;使用sort工具可以对RAM有限的任意大文件进行排序;等等

最新更新