我有一些配置文件(实际上是从防火墙报告中导出),使用这种结构:
policies {
apply-groups default-log;
from-zone Trust to-zone DMZ {
policy policy-66 {
match {
source-address g_DMZ_SRV_;
destination-address g_DMZ_SRV;
application any;
}
then {
permit;
}
}
policy policy-9 {
match {
source-address g_h_OpenMail-Server;
destination-address g_in_DMZ_Exchange;
application t_1023;
}
then {
permit;
}
}
}
from-zone DMZ to-zone Blabla {
policy policy-68 {
match {
source-address g_DMZ_SRV_2_;
destination-address g_DMZ_SRV_3;
application T_22-ssh;
}
then {
permit;
}
}
policy policy-95 {
match {
source-address g_h_OpenMail-Server-2;
source-address 1.2.0.3;
destination-address g_in_DMZ_Exchange-1;
destination-address 10.25.32.64;
application t_1024;
}
then {
permit;
}
}
}
}
并且我想在Perl中解析它,以便构建一个哈希,例如(或简单地设置条件来处理数据),我可以在之后利用它,例如:
Trust-to-DMZ
policy-66
source => g_DMZ_SRV
destination => blabla
policy-44
source => source1
source2
source3
destination => dest1
ports => port1
DMZ-to-Trust
policy-XX
我想知道:
如果你知道某些模块帮助完成这样的任务(我想我可以使用Text :: Balanced,我在其他一些帖子中找到了一些例子)
是否有一些方法/最佳做法可以避免肮脏的工作?
我想我可以“计算”大括号的数量并在循环中做循环..但它会很脏。
是否有更简单的解决方案或模块自动执行此操作? (比如存在XML文件的模块,例如, XML ::简单将XML的内容放入哈希中,我会期望类似的东西?)
否则我会开始编写脏东西并在此处发布我的进度
谢谢!
6月8日编辑,只是你知道,它适用于脏的脏脏代码(我不是开发人员,道歉),这不是我想要的,因为它是不适应..而且显然很脏 你被警告了! :)所以如果你不想要血液,请不要看它
use warnings;
use lib '/opt/csm/64-bit/cpan/5.16.3-2013.03/lib';
use Data::Dumper;
my ( $policies_flag, $fromzone_flag, $policy_flag, $match_flag, $zone_flag ) = ( 0,0,0,0,0 );
my ( $details_flag, $clos_flag, $then_flag, $permit_flag, $clos2_flag, $final_flag ) = ( 0,0,0,0,0,0 );
my $fromzone;
my $tozone;
my %pols;
my $clos_counter;
die "Usage: $0 <path_to_file>" if $ARGV[0] eq '';
open D, '<', $ARGV[0] or die "cannot open $ARGV[0] for read\n";
@data = <D>;
close D;
OUTER: foreach my $str (@data) {
next if $str =~ /^$/;
next if $str =~ /apply-groups/;
chomp $str;
if ( $str =~ /\s*policies\s+\{/ ) {
$policies_flag = 1;
next OUTER;
}
# policies
if ($policies_flag == 1) {
if ($str =~ /from-zone\s\S+\sto-zone\s\S+\s\{$/) {
next if $str =~ /(<|>)/;
( $fromzone, $tozone ) = ( split(/\s+/,$str) )[2,4];
$fromzone_flag = 1;
next OUTER;
}
# from-zone
if ($fromzone_flag == 1) {
if ($str =~ /policy\s+\S+\s+\{/) {
$policy_flag = 1;
$clos_counter=0;
( $policy_name ) = ( split(/\s+/, $str) )[2];
$pols{$policy_name}{from_zone} = "$fromzone";
$pols{$policy_name}{to_zone} = "$tozone";
next OUTER;
}
# pol
if ($policy_flag == 1) {
if ($str =~ /match\s+\{/) {
$match_flag = 1;
next OUTER;
}
}
# match
if ($match_flag == 1) {
if ($str =~ /\S+\s+\S+;$/) {
$details_flag = 1;
if ($str =~ /source-address/) {
( $sources ) = ( split(/\s+/, $str) )[2];
$sources =~ s/;//;
push( @{$pols{$policy_name}{sources}}, "$sources");
} elsif ($str =~ /destination-address/) {
( $dests ) = ( split(/\s+/, $str) )[2];
$dests =~ s/;//;
push( @{$pols{$policy_name}{destinations}}, "$dests");
} elsif ($str =~ /application/) {
( $ports ) = ( split(/\s+/, $str) )[2];
$ports =~ s/;//;
push( @{$pols{$policy_name}{ports}}, "$ports");
}
next OUTER;
}
}
# rest
if ($details_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 0) {
$clos_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# then
if ($clos_flag == 1) {
if ($str =~ /\s*then\s+\{$/) {
$then_flag = 1;
next OUTER;
}
}
# permit
if ($then_flag == 1) {
if ($str =~ /\s*permit;$/) {
$permit_flag = 1;
$pols{$policy_name}{action} = ( split(/\s+/,$str) )[1];
next OUTER;
}
}
# clos2
if ($permit_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 1) {
$clos2_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# final close
if ($clos2_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 2) {
$final_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# ultimate zone
if ($final_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 3) {
$zone_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# ulti pols
if ($zone_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 4) {
$clos_counter++;
last OUTER;
}
}
}
}
}
}
print Dumper(\%pols);
给出:
$VAR1 = {
'policy-68' => {
'ports' => [
'T_22-ssh'
],
'sources' => [
'g_DMZ_SRV_2_'
],
'to_zone' => 'Blabla',
'from_zone' => 'DMZ',
'action' => 'permit;',
'destinations' => [
'g_DMZ_SRV_3'
]
},
'policy-9' => {
'ports' => [
't_1023'
],
'sources' => [
'g_h_OpenMail-Server'
],
'to_zone' => 'DMZ',
'from_zone' => 'Trust',
'action' => 'permit;',
'destinations' => [
'g_in_DMZ_Exchange'
]
},
'policy-66' => {
'ports' => [
'any'
],
'sources' => [
'g_DMZ_SRV_'
],
'to_zone' => 'DMZ',
'from_zone' => 'Trust',
'action' => 'permit;',
'destinations' => [
'g_DMZ_SRV'
]
},
'policy-95' => {
'ports' => [
't_1024'
],
'sources' => [
'g_h_OpenMail-Server-2',
'1.2.0.3'
],
'to_zone' => 'Blabla',
'from_zone' => 'DMZ',
'action' => 'permit;',
'destinations' => [
'g_in_DMZ_Exchange-1',
'10.25.32.64'
]
}
};
答案 0 :(得分:1)
在我的或许不完全公正的意见中,Marpa::R2是解决问题类型的好方法。
答案 1 :(得分:1)
my($parser) = Text::Balanced::Marpa -> new ( open => ['{'], close => ['}'], ); my($text) = read_text('policies.txt'); my($result) = $parser -> parse(text => \$text); print "Parse result: $result (0 is success)\n"; #print join("\n", @{$parser -> tree -> tree2string}), "\n"; my($indent); for my $node ($parser -> tree -> traverse($parser -> tree -> POST_ORDER) ) { $indent = ' ' x $node -> depth; $text = ${$node -> meta}{text} =~ s/\n|[{}]//gr; say $indent, $text if ($text); }
Output:
Parse result: 0 (0 is success)
policies
apply-groups default-log; from-zone Trust to-zone DMZ
policy policy-66
match
source-address g_DMZ_SRV_; destination-address g_DMZ_SRV; application any;
then
permit;
policy policy-9
match
source-address g_h_OpenMail-Server; destination-address g_in_DMZ_Exchange; application t_1023;
then
permit;
from-zone DMZ to-zone Blabla
policy policy-68
match
source-address g_DMZ_SRV_2_; destination-address g_DMZ_SRV_3; application T_22-ssh;
then
permit;
policy policy-95
match
source-address g_h_OpenMail-Server-2; source-address 1.2.0.3; destination-address g_in_DMZ_Exchange-1; destination-address 10.25.32.64; application t_1024;
then
permit;
This gist包含上面的代码和输出。 Stackoverflow的格式化程序坚持要对所有内容进行缩进,无论它是否理解 - 可以依靠gist包含一个预先损坏的副本。