Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我如何包括所有/部分“信息”;“子模块”;在Perl脚本中?_Perl_Perl Module - Fatal编程技术网

我如何包括所有/部分“信息”;“子模块”;在Perl脚本中?

我如何包括所有/部分“信息”;“子模块”;在Perl脚本中?,perl,perl-module,Perl,Perl Module,首先我要说的是,我对创建Perl模块一点经验都没有,所以如果我离这里很远的话,我很抱歉 假设我正在创建几个模块: foo::bar foo::bar::a foo::bar::b 由于我不知道它们被称为什么,我将a.pm和b.pm模块称为“子模块”,因为它们与bar.pm模块相关,但可能仍然有些独立 因此,我的一个Perl脚本可以使用foo::bar::a,另一个脚本可以使用foo::bar::b,也许我还有另一个脚本需要同时使用“a”和“b”中的函数。不要这样说: use foo::bar;

首先我要说的是,我对创建Perl模块一点经验都没有,所以如果我离这里很远的话,我很抱歉

假设我正在创建几个模块:

foo::bar
foo::bar::a
foo::bar::b
由于我不知道它们被称为什么,我将a.pm和b.pm模块称为“子模块”,因为它们与bar.pm模块相关,但可能仍然有些独立

因此,我的一个Perl脚本可以使用foo::bar::a,另一个脚本可以使用foo::bar::b,也许我还有另一个脚本需要同时使用“a”和“b”中的函数。不要这样说:

use foo::bar;
use foo::bar::a qw(one two);
use foo::bar::b;
我想这样做:

use foo::bar qw(:a :b);
在我看来,这将使我的脚本能够访问bar.pm、a.pm和b.pm中的所有内容

我做了这样的测试,显然我错了


这样的事情可能吗?我想我可以让bar.pm使用a.pm和b.pm,然后使用“包装器”函数将调用传递到“子模块”,但似乎有一种更简单的方法。

是的,您可以这样做。它可能需要在foo::bar中编写一个自定义的“子导入”,以您想要的方式解释传入的参数

可能您现在正在使用Exporter,问题在于它缺乏对语法的支持。您会发现模块语法导出器实现没有什么特别之处;这只是一个普通的惯例。不过,您可能希望了解it是如何开展业务的,以了解您希望如何开展业务。

还可以尝试查看我的模块,以获取有关如何开展业务的示例。即使你能做到,我从来都不太喜欢这个结果。您可能需要考虑插件或MIXIN方法。上有一些模块可以帮助实现这一点

下面是我为Test::Data编写的自定义
import

sub import { my $self = shift; my $caller = caller; foreach my $package ( @_ ) { my $full_package = "Test::Data::$package"; eval "require $full_package; 1"; if( $@ ) { carp "Could not require Test::Data::$package: $@"; } $full_package->export($caller); } } 次级进口 { 我的$self=shift; 我的$caller=caller; foreach my$套餐(@) { my$full_package=“Test::Data::$package”; 评估“需要$full_套餐;1”; 如果($@) { carp“无法要求测试::数据::$package:$@”; } $full_package->export($caller); } }
是的,但您必须装配自己的导入子组件:

use strict;
use warnings;

package ab;
use base qw<Exporter>;
our @EXPORT_OK;
our %EXPORT_TAGS;
BEGIN { 
    @EXPORT_OK   = qw<>;
    %EXPORT_TAGS = ( a => 1, b => 1, all => \@EXPORT_OK );
}

sub setup_part { 
    #use Smart::Comments;
    my $code = shift;
    my $mini_path = "foo/bar/$code.pm";
    return if exists $INC{$mini_path};
    require $mini_path; 
    my $arr_ref 
        = do { no strict 'refs';
            \@{Symbol::qualify( 'EXPORT_OK', $code )};
        };
    $code->import( @$arr_ref );
    push @EXPORT_OK, @$arr_ref;
    $EXPORT_TAGS{$code} = [ @$arr_ref ];
    return;
}

sub import { 
    my ( $package_name, @imports ) = @_;
    my %import_hash = map { $_ => 1 } @imports;
    if ( exists $import_hash{':all'} ) { 
        @import_hash{qw<:a :b>} = ( 1, 1 );
    }
    foreach my $import ( grep { exists $import_hash{$_} } qw<:a :b> ) { 
        setup_part( substr( $import, 1 ));
    }
    goto &{Exporter->can( 'import' )};
}

1;
使用严格;
使用警告;
包装ab;
使用基本qw;
我们的@EXPORT\u OK;
我们的%出口标签;
开始{
@导出_OK=qw;
%导出标记=(a=>1,b=>1,all=>\@EXPORT\u确定);
}
子设置_部分{
#使用Smart::注释;
我的$code=shift;
my$mini_path=“foo/bar/$code.pm”;
如果存在$INC{$mini_path},则返回;
需要$mini_path;
我的$arr\u ref
=do{没有严格的'refs';
\@{Symbol::qualify('EXPORT_OK',$code)};
};
$code->import(@$arr\u ref);
按@EXPORT_OK,@$arr_ref;
$EXPORT_TAGS{$code}=[@$arr_ref];
返回;
}
次级进口{
我的($package_name,@imports)=@;
我的%import\u hash=map{$\u=>1}@imports;
如果(存在$import_hash{):all'}{
@导入_散列{qw}=(1,1);
}
foreach my$import(grep{exists$import_hash{$}}qw){
设置部分(substr($import,1));
}
转到&{Exporter->can('import')};
}
1.

如果您不知道模块的名称,为什么要包括它?你不应该把它包括在内。只在需要它的(调用)模块中包含一个模块,而不包括其他模块


也就是说:如果你正在使用它,那么就“使用”它。如果你不使用它,就不要“使用”它。

我已经找到了一个类似于最近的解决方案。我知道-太老了-但我想评论一下brian d foy的答案(2009年2月12日17:55),但遗憾的是我没有足够的声誉来完成这项工作。这就是为什么我添加我的评论作为一个新的回应

他的回答帮助我解决了与最近类似的问题。但如果与
use lib
一起使用,则需要进行一些修改

我有一堆模块,看起来像
a::B::*
。这些应该由常规模块
A::B
加载到脚本中。所有这些模块都位于与加载脚本相同的目录下的文件中。使用brian d foy建议的机制,我们可以得到许多重新定义的子程序错误。为了避免所有这些问题,我相信,我找到了一个更好的解决方案,比没有警告“重新定义”要好。现在我们可以在主脚本中自由使用
use lib
无警告“重定义”
shift@INC,…

sub import { @TAGS = ( @_ ); my $me = shift @TAGS; ( my $pm = $me ) =~ s|::|/|g; $pm .= ".pm"; ( $dir = $INC{$pm} ) =~ s/\.pm$//; foreach ( glob "$dir/*.pm" ) { /(\w+)\.pm$/; my $module = "${me}::$1"; eval "use $module qw(:all)"; # You are free to use any items in the exporting list die "$me: Error while loading $module from $_: $@\n" if $@; } # Fill in @EXPORT_OK and %EXPORT_TAGS manually from each A::B::*::EXPORT_OK # ... goto &{ Exporter->can( "import" ) }; } 次级进口{ @标签=(@); my$me=shift@TAGS; (my$pm=$me)=~s |::|/| g; $pm.=“.pm”; ($dir=$INC{$pm})=~s/\.pm$/; foreach(全局“$dir/*.pm”){ /(\w+)\.pm$/; my$module=“${me}::$1”; eval“使用$module qw(:all)”#您可以自由使用导出列表中的任何项目 如果$@,则从$\:$@\n加载$module时出现“$me:Error”; } #手动填写@EXPORT_OK和%EXPORT_标签,每个A::B::*::EXPORT_OK # ... 转到&{Exporter->can(“import”)}; }
是的,我用的是Exporter。好的一点——我确信我的语法是不正确的——我并不是想把责任推到导出器模块上。我不是想说你做错了什么。我的意思是,您所做的(可能)超出了出口商的范围/使命,需要您自己实施。(虽然你可能也应该彻底阅读出口商的文档;也许可以教它这么做。)哦,没问题。我查看了出口商的文件,发现了出口标签,这正是我所想的——但我无法让它正确工作!这里是您的Test::Data模块的第一行:“Test::Data模块只是从Test::Data::*模块中移植函数。”这正是我想要的——只是它不像我想的那样直截了当。谢谢你的解决方案