我要重构大量旧的perl脚本。 (超过150k行,没有测试,没有严格,没有包,没有提交日志,没有评论)
当我开始在t
目录下编写一些测试时。我发现几乎所有文件require
都是绝对路径。所以我尝试使用内置的require
函数来使它们可移植,但没有运气:
use strict;
use warnings;
use Test::More;
use FindBin;
BEGIN {
my $root = "$FindBin::RealBin/../";
sub require {
$_[0] = $root . $_[0];
CORE::require(@_);
}
}
require_ok "foo.pl";
done_testing();
上面的脚本给了我:Error: Can't locate foo.pl in @INC...
如何在Perl需要之前添加根路径?
谢谢Axeman,我使用以下钩子修改了绝对路径。
my $root = "$RealBin/../";
unshift @INC, sub {
my ($coderef, $filename) = @_;
$filename =~ s/^\///;
open(FILE, '<', $root . $filename);
return *FILE;
};
答案 0 :(得分:6)
你不是只是在寻找
use FindBin qw( $RealBin );
use lib "$RealBin/..";
答案 1 :(得分:4)
你不必。
当模块为require
时,无论是require
还是use
,perl都会查看列表以查看它是否可以通过(通常)目录列表找到模块作为安装库。此列表存储在名为@INC
的变量中。
但是,@INC
需要的不仅仅是目录,它还需要“钩子”,这些子程序可以改变Perl模块的加载行为。如果您插入 hook (子例程)作为@INC
的第一个条目,则require将调用您的行为。
您可以在perldoc on require
找到更完整的治疗方法。我只想快速介绍一个钩子:
sub inc_hook {
my ( $ref_to_this_sub, $relative_module_path ) = @_;
# $relative_module_path will be in directory form: Root/Package.pm
# return nothing to pass it to standard behavior
return unless _i_want_to_handle( $relative_module_path );
# most commonly, return handle to source
return my $io_handle_to_source = handle_module( $relative_module_path );
}
unshift @INC, inc_hook;