目前使用perl来解析由多个Sections组成的配置文件,而这些配置文件又可以包含多个定义。我的实际文件有一个完全不同的主题,但我的解析器也会解析这个例子:
SECTION Foo
HP 200
ATT 50 Slap
ATT 100 Kick
DESC This is Foo. What is love?
SECTION Bar
HP 2
ATT 1 Mumble
DESC This is Bar. Baby don't hurt me!
现在,我的解析器主要使用三个变量来存储数据:
my %sections;
my $parsedName;
my %parsedVars;
在阅读SECTION Bar
时,它已填写如下:
%sections = (); # empty
$parsedName = "Foo";
%parsedVars = (
"HP" => "200",
"ATT" => ("50 Slap","100 Kick"),
"DESC" => "This is Foo. What is love?",
);
我认为你明白了。现在,%parsedVars
字段的内容已经过验证,如果成功,整个内容将存储到%sections
,这是我在那里使用的代码:
use Storable qw(dclone);
# (...)
# Clone the Variables
$sections{$parsedName} = dclone (\%parsedVars);
# Prepare for next section
$parsedName = getSectionName $currentLine;
undef %parsedVars;
这就是伤害的部分,因为我并不想真正复制整个%parsedVars
,而且我也不允许包含任何内容但由于严格限制的运行时环境,strict
。
我觉得我应该从其名称中删除哈希并将其附加到$sections{$parsedName}
,但我无法理解如何完成这项工作。
# These hiccups aside,
# my parser works fine, which is nice.
# One completeness wide:
# Result looks like this, no surprise!
%sections = (
"Foo" => (
"HP" => "200",
"ATT" => ("50 Slap","100 Kick"),
"DESC" => "This is Foo. What is love?",
),
"Bar" => (
"HP" => "2",
"ATT" => "1 Mumble",
"DESC" => "This is Bar. Baby don't hurt me!",
),
);
答案 0 :(得分:1)
use strict;
use warnings;
my %data;
my $section;
while (<DATA>) {
chomp;
next if /^\s*$/;
my ( $key, $val ) = split ' ', $_, 2;
if ( $key eq 'SECTION' ) {
$section = $val;
} else {
push @{ $data{$section}{$key} }, $val;
}
}
# Collapse single element arrays:
for ( values %data ) {
for ( values %$_ ) {
$_ = $_->[0] if @$_ == 1;
}
}
use Data::Dump;
dd \%data;
__DATA__
SECTION Foo
HP 200
ATT 50 Slap
ATT 100 Kick
DESC This is Foo. What is love?
SECTION Bar
HP 2
ATT 1 Mumble
DESC This is Bar. Baby don't hurt me!
输出:
{
Bar => { ATT => "1 Mumble", DESC => "This is Bar. Baby don't hurt me!", HP => 2 },
Foo => {
ATT => ["50 Slap", "100 Kick"],
DESC => "This is Foo. What is love?",
HP => 200,
},
}
答案 1 :(得分:0)
一种方法是将parsedVars声明为包含哈希引用而不是哈希的标量。
当您开始解析每个部分时:
$parsedVars = {}; # Allocate a new hash
# store variables in the hash as you would before, but don't forget
# to dereference the hash ref!
# when finished parsing the section:
$sections{$parsedName} = $parsedVars;
另一种方法是在输入文件中为每个部分输入的范围内本地声明%parsedVars。这样,每次进入示波器时,都会得到一个新的哈希值:
while (<FILE>) {
if (/^SECTION: (\w)+/) {
$parsedName=$1;
my %parsedVars; # this is the new hash, allocated
# each time a new section is allocated
# parse the variables as before, storing in the hash
# when done:
$sections{$parsedName} = \%parsedVars;
}
}