无论如何要告诉perl脚本是否通过do运行?
我有一个从主脚本加载的小脚本配置文件。
#main.pl
package MYPACKAGE;
our $isMaster=1;
package main;
my config=do "./config.pl"
#config.pl
my $runViaDoFlag;
$runViaDoFlag=$0=~/main.pl/; #Test if main.pl is the executing script
$runViaDoFlag=defined $MYPACKAGE::isMaster; #Test custom package variable
#Is there a 'built-in' way to do this?
die "Need to run from main script! " unless $runViaDoFlag;
{
options={
option1=>"some value",
option2=>"some value",
},
mySub=>sub {
# do interesting things here
}
}
在更复杂的配置文件中,config.pl 脚本仅由do. 因此我想包含一个die基本的使用说明。
解决方案:
- 测试
$0主脚本名称 - 在主脚本中定义自定义包变量并由配置脚本检查
- 只需在配置中添加注释,指导用户如何使用它。
这些工作,但是有没有办法知道脚本是否通过内置变量/子执行执行?
回答
我会提供设计上的更改:将该配置放在一个普通模块中,然后您可以在其中测试它是否已被(从) main::命名空间。那么就不需要任何带有控制变量等的杂技了。
一种方法来做到这一点
use warnings;
use strict;
use feature 'say';
use FindBin qw($RealBin);
use lib $RealBin; # so to be able to 'use' from current directory
use ConfigPackage qw(load_config);
my $config = load_config();
# ...
和ConfigPackage.pm(在同一目录中)
package ConfigPackage;
use warnings;
use strict;
use feature 'say';
use Carp;
use Exporter qw(); # want our own import
our @EXPORT_OK = qw(load_config);
sub import {
#say "Loaded by: ", (caller)[0];
croak "Must only be loaded from 'main::'"
if not ( (caller)[0] eq 'main' );
# Now switch to Exporter::import to export symbols as needed
goto &Exporter::import;
}
sub load_config {
# ...
return 'Some config-related data structure';
}
1;
(请注意,这个使用goto语句是好的。)
这当然只是一个草图;根据需要进行调整、进一步发展和修改。如果这是从 lodaed 以外的包中提取出来的main::,因此它失败了,那么这将发生在编译阶段,因为那是调用import的时候。我会认为这是一件好事。
如果该配置代码也需要能够运行,如问题所示,那么有一个单独的可执行文件来加载此模块并运行需要运行的内容。
至于所述的问题,标题和问题的(明显)任务略有不同,但都可以通过使用调用者 EXPR来处理。不过,它不会是一个干净的小“内置”调用。
关于事情做的目的是可以使用的是
do'./stat.pl'在很大程度上就像eval `cat stat.pl`;除了那个 ...
(stat.pl早先在文档中介绍过,只是为了表示do在文件上调用。)
然后caller(0)将提供明确的提示(参见文档)。它返回
my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash) = caller($i);
在要求, 的调用中do './config.pl',除了main(package) 和正确的文件名之外,caller(0)inconfig.pl还返回:
-
(eval)为了$subroutine -
./config.pl为了$evaltext -
1为了$is_require
总而言之,这足以决定是否按要求进行了调用。
但是,我不会推荐这种复杂的分析,而不仅仅是使用包,这也更加灵活。