在Perl中,为什么我会得到"未定义的子程序"在perl模块中但不在main中?

时间:2017-12-19 15:05:10

标签: perl

我得到了一个"未定义的子程序"对于下面代码中的sub2而不是sub1。

这是perl脚本(try.pl)...

#!/usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

use FindBin qw($Bin);
use lib "$Bin";
use try_common;

print "Running try.pl\n";
sub1("echo \"in sub1\"");
sub2("echo \"in sub2\"");

exit;

sub sub1 {

(my $cmd) = @_;

print "Executing... \"${cmd}\"\n";
my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
print "${stdouterr}\n";

return;
}

这是try_common.pm ...

#! /usr/bin/env perl

use strict;
use IO::CaptureOutput qw(capture_exec_combined);

package try_common;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
  sub2
);

sub sub2 {

    (my $cmd) = @_;

    print "Executing... \"${cmd}\"\n";
    my ($stdouterr, $success, $exit_code) = capture_exec_combined($cmd);
    print "${stdouterr}\n";

    return;
}

1;

当我运行try.pl时,我得到了......

% ./try.pl
Running try.pl
Executing... "echo "in sub1""
in sub1

Executing... "echo "in sub2""
Undefined subroutine &try_common::capture_exec_combined called at 
/home/me/PERL/try_common.pm line 20.

这看起来像某种范围问题,因为如果我剪切/粘贴"使用IO :: CaptureOutput qw(capture_exec_combined);"作为sub2的第一行,它的工作原理。这在try.pl中是不必要的(它运行sub1 OK),但perl模块中存在问题。嗯......

在预先感谢您的帮助!

4 个答案:

答案 0 :(得分:6)

您在声明程序包之前通过capture_exec_combined子句导入use,因此它已导入main程序包,而不是try_common。进一步移动包声明。

答案 1 :(得分:4)

您应该查看perlmod文档以了解模块的工作原理。简而言之:

  1. 当您使用package A(在Perl 5中)时,您将以下代码的命名空间更改为A,并且在该点之后的所有全局符号(例如子例程)定义将进入那个包裹。范围内的子例程不需要导出,并且可以在其范围名称前面使用:A::function。你似乎找到了这个。

  2. Perl使用package作为创建模块的方法,并将代码拆分为不同的文件,但也作为其面向对象功能的基础。

  3. 大多数情况下, modules 由名为Exporter的特殊核心模块处理。见Exporter。此模块使用一些变量来了解要执行的操作,例如@EXPORT@EXPORT_OK@ISA。第一个定义了包含模块use Module时默认情况下应导出的名称。第二个定义了可以导出的名称(但需要用use Module qw(name1 name2)来提及。最后一个以面向对象的方式告诉你的模块。如果你不关心对象方向,您的模块通常“是”Exporter

  4. 另外,如另一个答案中所述,当您定义一个模块时,package module声明应该是文件中的第一个声明,因此它之后的任何内容都将在该范围内。

答案 2 :(得分:0)

我讨厌当我犯这个错误,虽然我不再做多了。你可以养成两种习惯:

最有可能的是,将整个文件作为包。第一行将是package语句,文件中不会显示其他package语句。

或者,使用新的PACKAGE BLOCK语法并将该包的所有内容放在块中。我这样做是为了我可能只在本地需要的小类:

package Foo {
    # everything including use statements go in this block
    }

答案 3 :(得分:-1)

我想我明白了。如果在perl模块中,我前缀为" capture_exec_combined"使用" ::",它可以工作。

仍然,为什么主要的,try.pl?

不需要这个