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

时间:2012-04-01 18:32:33

标签: perl shell

我想知道这里的最佳做法。假设我想获取文件某些行的内容。我可以使用单行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。我只是想让它保持一致。

建议做什么?

3 个答案:

答案 0 :(得分:14)

如果有操作的Perl函数,Perl认为你应该使用它的版本。但是,您举一个Perl 模块的示例,提供纯Perl方法。那是非常不同的。没有一个单一的答案(就像大多数情况一样),所以你必须自己决定做什么:

  • 纯Perl方法是否正确执行?例如,File::Copy有一些限制,因为它为用户做出了一些尴尬的决定,因此很多人认为它已经破裂了。例如,请参阅File::Copy versus cp/mv

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

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

  • 将复杂的参数 - 空格,引号和特殊字符 - 传递给外部命令会让你哭泣。你必须做很多繁琐的工作,以确保你正确处理论点。但Perl子程序并不在意。

  • 使用外部命令时,您必须更加注意自己在做什么。如果您只是致电rm,Perl将搜索您的PATH并使用名为rm的第一件事。这并不意味着它是你认为的程序。我在掌握Perl 的“安全编程技术”中写了很多相关内容。

  • 如果纯Perl方法需要一个模块,特别是如果该模块有许多复杂的依赖关系,那么你可能会依赖它或者分发它。

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

对于您的特定示例,我使用Perl。向awk倾斜,这是一个原型Perl,只是奇怪的。你应该能够做到perk所做的一切。如果您有一个awk程序,可以使用 a2p 程序将其转换为Perl:

 NR==5

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

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

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

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

我认为你应该避免使用其他程序以避免使用Perl代码。

要删除目录树,我喜欢File::Path。它有一些依赖项,但它们都在Perl标准库中。与该模块相关的疼痛很少(如果有的话)。我会一直使用它,直到遇到一个无效的问题。

答案 1 :(得分:4)

如果您希望自己的应用程序可以移植到非unix系统,那么绝对可以在Perl中编写所有代码。

如果没有,那真的取决于你......创建一个新进程的速度较慢,但​​如果它对任务不重要则无关紧要。我个人会选择能够更快实施的解决方案。

答案 2 :(得分:2)

在我看来,有效的代码应该是第一优先。例如,如果文件名中有空格,则会失败。

使用shell会使代码更难编码,因为您的程序需要正确生成另一个由sh运行的程序。 (如果使用多arg版本的系统来避免shell,这个问题就会消失。)

此外,使用外部工具会使处理错误变得困难。你甚至没有尝试过这样做!

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