我有一个看起来像这样的文件:
Alpha 27600
Beta 1
Charlie true
BEGIN Delta
BEGIN Epsilon Setting High Hook 50 END
BEGIN Foxtrot Corp 71 END
BEGIN "Jelly Bean" Corp 88 END
END
BEGIN Hotel
Height 25
Lawn 85
END
基本上它是由一个或多个空格分隔的几个键/值对。棘手的部分是可能嵌套的BEGIN / END块,可能跨越多行。我需要查看文件并根据BEGIN后面的内容采取一些措施。例如,如果它是Delta,我可能需要处理每个子BEGIN行,就好像它是Hotel,我可以完全跳过它。
我稍微看了一下Parse :: RecDescent,但不确定如何让它正确处理BEGIN / END情况。速度并不像拥有更容易理解和维护的解决方案那么重要。
有什么建议吗?
编辑:我喜欢米勒的解决方案,但随后查看数据意识到为什么我不只是分裂在空白上。一些标签中有一些空格。在上面的数据文件中添加了“Jelly Bean”标签以反映这一点。
答案 0 :(得分:3)
只需解析整个数据结构,过滤掉事后不需要的部分:
use strict;
use warnings;
use Text::ParseWords;
my @tokens = parse_line( qr{\s+}, 0, do { local $/; <DATA> } );
my %hash;
my @levels = \%hash;
while ( defined( my $key = shift @tokens ) ) {
if ( $key eq 'BEGIN' ) {
push @levels, $levels[-1]{ shift @tokens } = {};
} elsif ( $key eq 'END' ) {
pop @levels;
} else {
$levels[-1]{$key} = shift @tokens;
}
}
use Data::Dump;
dd \%hash;
__DATA__
Alpha 27600
Beta 1
Charlie true
BEGIN Delta
BEGIN Epsilon Setting High Hook 50 END
BEGIN Foxtrot Corp 71 END
BEGIN "Jelly Bean" Corp 88 END
END
BEGIN Hotel
Height 25
Lawn 85
END
输出:
{
Alpha => 27600,
Beta => 1,
Charlie => "true",
Delta => {
"Epsilon" => { Hook => 50, Setting => "High" },
"Foxtrot" => { Corp => 71 },
"Jelly Bean" => { Corp => 88 },
},
Hotel => { Height => 25, Lawn => 85 },
}
答案 1 :(得分:0)
就我个人而言,我会用Parser::MGC破解一些东西(虽然我可能因为我写了它而有偏见)。
使用scope_of
方法的嵌套范围可以轻松处理这些BEGIN
/ END
标记。