我有一个应用程序,我希望允许用户在Perl中指定配置文件。
我的想法类似于Arch中使用PKGBUILD的方式:它是一个Bash脚本,它只是来自“makepkg”工具的source
d。它包含变量和函数定义:
pkgbase=somepkg
pkgname=('somepkg')
pkgver=0.0.1
...
prepare() {
cd "${srcdir}/${pkgbase}-${pkgver}"
...
}
我想在Perl中做这样的事情。我想我正在寻找一个perl版本的source
,它可以读取文件,对其进行评估,并将所有子程序和变量导入调用者的命名空间。使用Bash版本,我可以想象写一个PKGBUILD来源另一个PKGBUILD,然后覆盖一个或两个变量;我希望在我的Perl配置文件中也可以使用这种“继承”。
Perl的do
的一个问题是它似乎将文件的变量和子例程放入一个单独的命名空间中。另外,我无法弄清楚如何覆盖真正的子例程,只命名为匿名子例程。
这是一个可以用来说明我想做什么的版本。它不是很优雅,但它演示了覆盖子例程和变量,以及调用先前定义的子例程:
$ cat test-override
#!/usr/bin/perl
use warnings;
use strict;
my @tables = qw(a b c);
my $print_tables = sub {
print join(", ", @tables), "\n";
};
eval(`cat "test-conf"`) or die "$@";
&$print_tables();
$ cat test-conf
@tables = qw(d e f);
my $old_print_tables = $print_tables;
$print_tables = sub {
warn "In test-conf \$print_tables\n";
&$old_print_tables();
}
$ ./test-override
In test-conf $print_tables
d, e, f
另一种方法是让配置文件返回一个哈希值,数据和子程序作为值。还可以选择使用类和继承。但是,我希望配置文件在语法上尽可能轻量级。
“do”的文档提到了在配置文件中使用Perl的可能性,所以我知道之前已经考虑过这个问题。是否有一个规范的例子,说明如何以“用户友好”的方式做到这一点?
您对此“配置文件”要做什么的描述(将子类和变量导入调用者的命名空间,覆盖子类,类,继承......)听起来像标准的Perl模块。所以使用标准的Perl模块。
请注意,这种方法有广泛的先例:标准的cpan
命令行客户端将其配置存储在一个模块中,该模块位于* nix类型系统上的~/.cpan/CPAN/MyConfig.pm
的默认路径上。当然,cpan
的MyConfig.pm
是一个非常简单的例子,它只设置了hashref $CPAN::Config
,但没有理由它也不能完成任何模块所做的所有其他事情。
但是使用do
这样做非常简单。我怀疑你只是在思考它:
$ cat test-override
#!/usr/bin/perl
use warnings;
use strict;
our @tables = qw(a b c);
sub print_tables {
print join(", ", @tables), "\n";
};
print_tables;
do "test-conf";
print_tables;
print "\@tables is @tables\n";
$ cat test-conf
@tables = qw(d e f);
sub print_tables {
print "print_tables from test_conf\n";
}
$ ./test-override
a, b, c
print_tables from test_conf
@tables is d e f
我使用@tables
做的重要更改是将它从my
更改为our
,print_tables
仅在当前范围和当前文件中可见,print_tables
在同一个包中的任何位置都可见(如果它使用包名称限定,则从其他包中可见)。
但是我的配置文件中的&main::print_tables
并没有调用原来的use
,你只是运气不好。因为只能有一个my
,所以完全取代它会覆盖原来不再存在的那个。如果你想能够覆盖它并且仍然能够调用原始的,你需要将两个声明放入不同的包中,这意味着使用OO Perl(这样你就可以多态地调用正确的一个) )。
另请注意,use strict; use warnings;
具有与use warnings;
相同的词汇范围,这意味着您的test-conf
不会延续到conf文件中。您可以通过在我的Subroutine print_tables redefined
版本中添加qazxswpoi来轻松演示这一点,然后它将生成警告qazxswpoi。