Perl模块或方法来抓取嵌套大括号内的数据?

问题描述:

我一直在使用那种结构的(从事实上防火墙报告出口)一些配置文件:Perl模块或方法来抓取嵌套大括号内的数据?

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 

我想要想知道:

  1. ,如果你知道一些模块在这样的任务帮助(我想我可以使用文本::平衡,我发现在其他几个职位的一些例子)

  2. 如果有这样做的一些方法/最佳做法,以避免肮脏的工作?

我想我可以“计数”大括号的数量,并在循环中做循环..但它会很脏。

是不是有一个更简单的解决方案或模块自动执行此操作? (如模块存在,例如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

这听起来像是我的一个马尔帕任务。但是我必须阅读大量的文档才能构建它。 – simbabque

+0

你在说Marpa :: R2吗?不用担心,我不希望人们代码而不是我编写代码,只是想知道是否有人已经这样做了,并且如果模块确实存在以便做到“简单”(就像XML :: Simple对XML文件所做的一样成哈希例如),我会看看马尔帕,感谢您的提示! – olivierg

+0

什么工具准确地产生这个输出?也许有什么关于cpan的?如果没有,建立它并把它放在那里。 – simbabque

在我也许并不完全公正的意见,Marpa::R2是一个好办法解决你的问题类型。

的马尔巴社会的罗恩·萨维奇想出了以下内容:

 

    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包含上面的代码和输出。 *的格式化程序坚持要缩进所有的东西,不管它是否理解 - 可以依靠这个要点来包含一个预损坏的副本。