我如何可以覆盖我的Perl程序硬编码的配置?
-
21-08-2019 - |
题
我有一个Perl脚本,设置变量接近顶部的目录,它会使用文件。这还需要几个变量被设置为命令行参数。 例如:
use Getopt::Long;
my ($mount_point, $sub_dir, $database_name, $database_schema);
# Populate variables from the command line:
GetOptions(
'mount_point=s' => \$mount_point,
'sub_dir=s' => \$sub_dir,
'database_name=s' => \$database_name,
'database_schema=s' => \$database_schema
);
# ... validation of required arguments here
################################################################################
# Directory variables
################################################################################
my $input_directory = "/${mount_point}/${sub_dir}/input";
my $output_directory = "/${mount_point}/${sub_dir}/output";
my $log_directory = "/${mount_point}/${sub_dir}/log";
my $database_directory = "/db/${database_name}";
my $database_scripts = "${database_directory}/scripts";
################################################################################
# File variables
################################################################################
my $input_file = "${input_dir}/input_file.dat";
my $output_file = "${output_dir}/output_file.dat";
# ... etc
这工作在我的开发,测试和生产环境优良。不过,我试图使它更容易忽略某些变量(无需进入调试器)用于开发和测试。 (例如,如果我想设置我的INPUT_FILE =“/tmp/my_input_file.dat”)。我的想法是使用GetOptions函数来处理这个问题,是这样的:
GetOptions(
'input_directory=s' => \$input_directory,
'output_directory=s' => \$output_directory,
'database_directory=s' => \$database_directory,
'log_directory=s' => \$log_directory,
'database_scripts=s' => \$database_scripts,
'input_file=s' => \$input_file,
'output_file=s' => \$output_file
);
GetOptions只能被调用一次(据我所知)。第4个参数,我的第一SNIPPIT需要,直接在上面最后7是可选的。我认为理想的情况下将设置默认为我的第一个代码片段,然后以某种方式超越任何人,如果论点在命令行通过已设定。我想到了存储在哈希我的所有选项,然后设置了,除非一个条目中的散列中存在的默认值的每个变量在使用散列,但似乎增添了不少额外的逻辑。有没有办法来调用两个不同的地方GetOptions脚本?
如果让任何意义不确定。
谢谢!
解决方案
下面的另一种方法。它使用名称的阵列和存储选项的哈希值。它使所有的选择确实是可选的,但除非你在命令行上“--debug”验证所需的项目。不管你是否使用“--debug”,您可以覆盖任何其他人。
您可以做更明确的逻辑检查,如果这对你很重要的,当然。我列入“--debug”作为如何忽略基本的选项,如“装入点”,如果你只是要覆盖“INPUT_FILE”和“OUTPUT_FILE”变量反正一个例子。
的主要思想这里是通过保持套选项名称的数组中,可以包括对所述组逻辑检查以相对少的代码。
use Getopt::Long;
my @required_opts = qw(
mount_point
sub_dir
database_name
database_schema
);
my @internal_opts = qw(
input_directory
output_directory
log_directory
database_directory
database_scripts
input_file
output_file
);
my @opt_spec = ("debug", map { "$_:s" } @required_opts, @internal_opts);
# Populate variables from the command line:
GetOptions( \(my %opts), @opt_spec );
# check required options unless
my @errors = grep { ! exists $opts{$_} } @required_options;
if ( @errors && ! $opts{debug} ) {
die "$0: missing required option(s): @errors\n";
}
################################################################################
# Directory variables
###############################################################################
my $opts{input_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/input";
my $opts{output_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/output";
my $opts{log_directory} ||= "/$opts{mount_point}/$opts{sub_dir}/log";
my $opts{database_directory} ||= "/db/$opts{database_name}";
my $opts{database_scripts} ||= "$opts{database_directory}/scripts";
################################################################################
# File variables
################################################################################
my $opts{input_file} ||= "$opts{input_directory}/input_file.dat";
my $opts{output_file} ||= "$opts{output_directory}/output_file.dat";
# ... etc
其他提示
这听起来像你需要改变你的程序使用的配置文件,而不是硬编码的配置。我专门掌握的Perl的一整章来此。你不希望更改源代码来测试程序。
有使配置文件容易特征上添加CPAN许多Perl模块。选择最适合您的输入数据之一。
一旦你的地方,你可以轻松地设置默认值,采取从多个地方(文件,命令行等)值,并且轻松地测试不同值的程序。获得更好的配置模型
我想我会做什么设置input_directory
等人以“民主基金”,然后把它们放在getopts的,再后来,测试,如果他们仍然民主基金,如果是将它们分配如图所示。如果用户在技术上是复杂的不够了解,“如果我给一个相对路径是相对于$mount_point/$sub_dir
”,那么我会做更多的分析寻找最初的“/".
GetOptions可以以与阵列作为输入数据被调用。阅读文档。