绑定读取和写入Perl配置文件
我正在使用我在上找到的PerlMonk示例: Configuration.pl:绑定读取和写入Perl配置文件,perl,file,configuration,tie,Perl,File,Configuration,Tie,我正在使用我在上找到的PerlMonk示例: Configuration.pl: %CFG = ( 'servers' => { 'SRV1' => { 'IP' => 99.32.4.0, 'user' => 'aname', 'pswd' => 'p4ssw0rd', 'status' => 'unavailable'
%CFG = (
'servers' => {
'SRV1' => {
'IP' => 99.32.4.0,
'user' => 'aname',
'pswd' => 'p4ssw0rd',
'status' => 'unavailable'
},
'SRV2' => {
'IP' => 129.99.10.5
'user' => 'guest',
'pswd' => 'guest'
'status' => 'unavailable'
}
},
'timeout' => 60,
'log' => {
'file' => '/var/log/my_log.log',
'level' => 'warn',
},
'temp' => 'remove me'
);
它工作得很好,但唯一的问题是读写类似散列的配置时“无序”。
有没有办法把它绑起来
这一点很重要,因为配置文件也将手动编辑,所以我希望键和值的顺序相同。您可以在使用前将配置变量绑定到一起,这样以后的散列键将保持与以前相同的顺序
use strict;
use warnings;
use Tie::IxHash;
tie my %CFG, 'Tie::IxHash';
%CFG = (
'servers' => {
'SRV1' => {
'IP' => '99.32.4.0',
'user' => 'aname',
'pswd' => 'p4ssw0rd',
'status' => 'unavailable'
},
'SRV2' => {
'IP' => '129.99.10.5',
'user' => 'guest',
'pswd' => 'guest',
'status' => 'unavailable'
}
},
'timeout' => 60,
'log' => {
'file' => '/var/log/my_log.log',
'level' => 'warn',
},
'temp' => 'remove me'
);
use Data::Dumper;
print Dumper \%CFG;
如果您使用,那么您的软件将不会受到恶意攻击(或者可能是意外损坏)。JSON的语法也比Perl数据结构简单,而且更容易从语法错误中恢复
设置canonical
选项将创建具有排序顺序的键的数据,因此每次为相同的Perl数据生成相同的输出。如果您需要数据的特定顺序,而不是字母顺序,那么您可以使用@mpapec在其答案中描述的模块
或者,您可以使用纯Perl版本的模块中的sort\u by
方法,该模块允许您传递排序规则子例程。这将允许您指定键的顺序,并且可以像使用哈希一样简单,该哈希将所有可能的键值与数字排序顺序关联起来
该程序使用sort_by
方法按照与原始散列中出现的键相同的顺序重建JSON。这不太可能是你想要的顺序,但机制是存在的。它通过查找哈希表中的每个键来确定它们应该如何排序。默认情况下,哈希中未出现的任何键(如SVR1
和SVR2
)都按字母顺序排序
use strict;
use warnings;
use JSON::PP ();
my %CFG = (
'servers' => {
'SRV1' => {
'IP' => '99.32.4.0',
'user' => 'aname',
'pswd' => 'p4ssw0rd',
'status' => 'unavailable'
},
'SRV2' => {
'IP' => '129.99.10.5',
'user' => 'guest',
'pswd' => 'guest',
'status' => 'unavailable'
}
},
'timeout' => 60,
'log' => {
'file' => '/var/log/my_log.log',
'level' => 'warn',
},
'temp' => 'remove me'
);
my %sort_order;
my $n = 0;
$sort_order{$_} = ++$n for qw/ servers timeout log temp /;
$sort_order{$_} = ++$n for qw/ IP user pswd status /;
$sort_order{$_} = ++$n for qw/ file level /;
my $json = JSON::PP->new->pretty->sort_by(\&json_sort);
print $json->encode(\%CFG);
sub json_sort {
my ($aa, $bb) = map $sort_order{$_}, $JSON::PP::a, $JSON::PP::b;
$aa and $bb and $aa <=> $bb or $JSON::PP::a cmp $JSON::PP::b;
}
它可以简单地保存到文件中,并以类似的方式还原。将数据存储为Perl代码是个坏主意。这样做会更好,这也解决了保持数据有序的问题。您还必须绑定所有内部哈希。您也可以将
$Data::Dumper::Sortkeys
设置为真值或对排序子例程的引用。@mob似乎有Tie::Autotie
,但哈希值应该一次填充一个键/值。mpapec&@mob,谢谢,我会尝试一下。。。即使是你,将每个内部散列绑定起来似乎也是一个杀手锏。我同意JSON可能更好,特别是因为我正在考虑将来将这个项目从Perl迁移到Python。关于IP地址的问题,我同意,我已经把它改成了字符串,我使用的例子来自原始的例子帖子。我已经测试了两个选项。。。我的配置文件有太多的内部散列,我懒得把它们都绑起来。因此,使用带有规范标记的JSON是合乎逻辑且经济高效的。谢谢。@tal.tzf:很高兴您找到了解决方案。@tal.tzf:JSON的纯Perl实现提供了一个sort_by
方法,允许您传递排序子例程。这可以让您指定键的顺序,也可以像使用散列一样简单,将所有可能的键值与数字排序顺序关联起来。@tal.tzf:我修改了我的答案,以显示如何通过使用sort\u by
方法传递自定义排序子例程来生成您喜欢的任何键顺序。
{
"servers" : {
"SRV1" : {
"IP" : "99.32.4.0",
"user" : "aname",
"pswd" : "p4ssw0rd",
"status" : "unavailable"
},
"SRV2" : {
"IP" : "129.99.10.5",
"user" : "guest",
"pswd" : "guest",
"status" : "unavailable"
}
},
"timeout" : 60,
"log" : {
"file" : "/var/log/my_log.log",
"level" : "warn"
},
"temp" : "remove me"
}