【问题标题】:Perl modules or method to grab data inside nested curly braces?Perl 模块或方法在嵌套的花括号内获取数据?
【发布时间】:2017-06-06 20:48:43
【问题描述】:

我有一些使用这种结构的配置文件(实际上是从防火墙报告中导出的):

 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. 如果你知道一些模块可以帮助完成这样的任务(我想我可以使用 Text::Balanced,我在其他一些帖子中找到了一些示例)

  2. 是否有一些方法/最佳实践可以避免脏活?

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

没有更简单的解决方案或模块自动执行此操作吗? (例如,XML 文件存在模块,XML::Simple 将 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'
                                         ]
                     }
    };

【问题讨论】:

  • 这对我来说听起来像是玛尔巴的任务。但我必须阅读大量文档才能构建它。
  • 你说的是 Marpa::R2 吗?不用担心我不指望人们代替我编写代码,只是想知道是否有人已经这样做了,以及模块是否确实存在以便“简单”地做到这一点(与 XML::Simple 对 XML 文件所做的方式相同)例如散列),我会看看 Marpa,谢谢你的提示!
  • 究竟是什么工具生成这个输出?也许cpan上有什么东西?如果没有,请构建它并将其放在那里。
  • 这是 Juniper ScreenOS 防火墙的导出配置(有一个名为“显示配置”的瞻博网络命令显示此内容),感谢提示我会查看是否存在。
  • 这可能是相关的:ns2html.sourceforge.net

标签: perl module nested curly-braces braces


【解决方案1】:

在我可能不是完全公正的意见中,Marpa::R2 是解决您的问题类型的好方法。

【讨论】:

    【解决方案2】:

    Marpa 社区的 Ron Savage 提出以下建议:

    my($parser) = Text::Balanced::Marpa -> new ( 打开 => ['{'], 关闭 => ['}'], ); my($text) = read_text('policies.txt'); 我的($result) = $parser -> 解析(text => \$text); print "解析结果:$result (0 为成功)\n"; #print join("\n", @{$parser -> tree -> tree2string}), "\n"; 我的($缩进); 对于我的 $node ($parser -> tree -> traverse($parser -> tree -> POST_ORDER) ) { $indent = ' ' x $节点 -> 深度; $text = ${$node -> meta}{text} =~ s/\n|[{}]//gr; 说 $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 包含损坏前的副本。

    【讨论】:

      猜你喜欢
      • 2013-04-21
      • 2011-01-07
      • 2017-02-27
      • 2020-04-27
      • 2013-06-30
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      相关资源
      最近更新 更多