加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在Perl脚本中分离配置数据和脚本逻辑

发布时间:2020-12-15 22:03:48 所属栏目:大数据 来源:网络整理
导读:我发现以下反模式在我的Perl脚本中重复:脚本包含一些机器/设置特定的设置,我在线存储为脚本中的常量,而脚本的其余部分是通用的: #!/usr/bin/perluse strict;use warnings;# machine specific settings at the start of the script.my $SETTING_1 = "foo";m
我发现以下反模式在我的Perl脚本中重复:脚本包含一些机器/设置特定的设置,我在线存储为脚本中的常量,而脚本的其余部分是通用的:
#!/usr/bin/perl

use strict;
use warnings;

# machine specific settings at the start of the script.
my $SETTING_1 = "foo";
my @SETTING_2 = ("123","456");
my $SETTING_3 = "something";

# general part of script follows.
...

这种模式在一台机器上运行时有点好,但是一旦我想将脚本分发到多台机器,麻烦就开始了,因为我必须保持跟踪,所以我不会在一般部分中用新的更新覆盖设置部分.

显然,正确的解决方案是具有一个通用脚本文件,并且读取一个特定于脚本运行的环境的配置文件.

我的问题是:您会推荐什么CPAN模块来解决这个问题?为什么?

解决方法

我最喜欢的是 Config::Std.我喜欢它处理 multi-line和 multi-part配置值的方式.

变量可能是多值时必须小心:如果配置文件中存在单个值,它将以标量存储该值;如果存在多个值,您将获得一个数组引用.

我发现有两个配置文件是方便的:一个用于描述操作环境的值(在哪里可以找到库等),另一个用于用户可修改的行为.

我也想写一个包装纸.例如(更新为包括自动生成的只读访问器):

#!/usr/bin/perl

package My::Config;
use strict; use warnings;

use Config::Std;
use FindBin qw($Bin);
use File::Spec::Functions qw( catfile );

sub new {
    my $class = shift;
    my ($config_file) = @_;

    $config_file = catfile($Bin,'config.ini');
    read_config $config_file => my %config;

    my $object = bless %config => $class;

    $object->gen_accessors(
        single => {
            install => [ qw( root ) ],},multi => {
            template => [ qw( dir ) ],);

    return $object;
}

sub gen_accessors {
    my $config = shift;
    my %args = @_;

    my $class = ref $config;

    {
        no strict 'refs';
        for my $section ( keys %{ $args{single} } ) {
            my @vars = @{ $args{single}->{$section} };
            for my $var ( @vars ) {
                *{ "${class}::${section}_${var}" } = sub {
                    $config->{$section}{$var};
                };
            }
        }

        for my $section ( keys %{ $args{multi} } ) {
            my @vars = @{ $args{multi}->{$section} };
            for my $var ( @vars ) {
                *{ "${class}::${section}_${var}" } = sub {
                    my $val = $config->{$section}{$var};
                    return [ $val ] unless 'ARRAY' eq ref $val;
                    return $val;
                }
            }
        }
    }

    return;
}

package main;

use strict; use warnings;

my $config = My::Config->new;

use Data::Dumper;
print Dumper($config->install_root,$config->template_dir);
C:Temp> cat config.ini
[install]
root = c:opt

[template]
dir = C:optapptmpl
dir = C:optcommontmpl

输出:

C:Temp> g.pl
$VAR1 = 'c:opt';
$VAR2 = [
          'C:optapptmpl','C:optcommontmpl'
        ];

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读