如何从相对位置使用Perl模块?

时间:2009-04-25 00:06:25

标签: perl module

我有一个名为foo的目录,其中我有libbinbin中的脚本需要lib中的内容。我做这样的事情:

#!perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib

但这意味着我必须在bin目录中运行脚本。当然有更好的方法。什么是正确的方法?

8 个答案:

答案 0 :(得分:48)

标准FindBin模块可以满足您的需求。

use FindBin;
use lib "$FindBin::Bin/../lib";

perldoc FindBin了解更多信息。

答案 1 :(得分:5)

通过.pl解析__FILE__的完整路径,并在最后添加../lib或弹出split(/\//,__FILE__)的最后一个元素并添加{{1}那个。

答案 2 :(得分:3)

“FindBin”模块仅在perl脚本所在的目录位于系统PATH中时才有效,否则将失败。要克服,您可以操纵$0值来获取路径到perl模块的信息,并将值传递给use lib

像这样 -

BEGIN {
    use File::Spec::Functions qw(rel2abs);
    use File::Basename qw(dirname);

    #Covert the script path to absolute and get its directory name
    our $path = dirname( rel2abs($0) );

    #Replace the bin tag with lib to get module directory
    $path =~ s{bin/?$}{lib};
}

use lib $path;

修改 FindBin模块工作得非常完美,可以按Michael's answer中的描述使用。我对其工作原理的理解是不完整的,因此我引发了我现在撤回的第一条评论。无论如何,我没有看到任何理由为什么这个方法不应该工作,尽管比使用FindBin(TMTOWTDI)可以实现的更多行。

答案 3 :(得分:3)

我通常使用这种技术。令人遗憾的是,我的PHP日子受到了启发:

在您知道给定文件相对于当前文件的位置,并且不确定可能在调用时调用它或周围环境的入口点的情况下,它非常方便。

但是,我通常会将此技术用于需要虚拟库来模拟事物的测试脚本。

use File::Basename ();
use Cwd            ();
my $base_dir;
my $relative_path; 
BEGIN {
    $realitive_path = '../../' # Path to base of project relative to the current file
    $base_dir = Cwd::realpath( File::Basename::dirname(__FILE__) .'/' . $relative_path );
}


use lib "${base_dir}/lib";
use Foo;

理想情况下应该有某个模块可以执行此操作,如果没有,我很想写一个:

use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ ); 

答案 4 :(得分:1)

use lib './';

在Linux机器上使用Perl v5.14.2为我工作,将文件包含在与我的脚本相同的目录中。

也许你可以在你的脚本工作目录下移动你的lib和bin目录并尝试使用

引用它们。
use lib './bin/';

答案 5 :(得分:0)

我的解决方案:

use lib substr(__FILE__, 0, rindex (__FILE__, "/"));

答案 6 :(得分:0)

只是将我自己的两分钱加到这个答案集中,我通常会使用以下内容来解决这个问题:

use lib do {
    use Cwd 'realpath';
    my ($dir) = __FILE__ =~ m{^(.*)/};  # $dir = path of current file
    realpath("$dir/../lib");            # path of '../lib' relative to $dir
};

我喜欢使用do块,因为所需的一切都整齐地包含在其中。如果您需要复制/粘贴,或者稍后尝试理解您的代码,则无需查找单独的BEGIN块或类似内容。

上面的代码天真地假设/用作目录/文件名分隔符。

答案 7 :(得分:-3)

怎么样:

BEGIN: {
    push @INC, '/full/path/to/lib';
}

要做一个相对引用会假设你要将它保存在bin目录中,所以改为在那里插入相对引用。