/ / Perl модули или метод, за да вземете данни във вложените фигурни скоби? - Perl, модул, вложени, фигурни скоби, скоби

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 :: Simple поставяне на съдържанието на XML в хеш, Бих очаквал нещо подобно за такива неща ?)

в противен случай ще започна да кодирам нещо мръсно и да публикувам напредъка си тук

Благодаря!

редактиране на 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 readn";
@data = <D>;
close D;


OUTER: foreach my $str (@data) {

next if $str =~ /^$/;
next if $str =~ /apply-groups/;
chomp $str;

if ( $str =~ /s*policiess+{/ ) {
$policies_flag = 1;
next OUTER;
}


# policies
if ($policies_flag == 1) {

if ($str =~ /from-zonesS+sto-zonesS+s{$/) {
next if $str =~ /(<|>)/;
( $fromzone, $tozone ) = ( split(/s+/,$str) )[2,4];
$fromzone_flag = 1;
next OUTER;
}

# from-zone
if ($fromzone_flag == 1) {

if ($str =~ /policys+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 =~ /matchs+{/) {
$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*thens+{$/) {
$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"
]
}
};

Отговори:

1 за отговор № 1

По мое вероятно не напълно обективно мнение, Марпа :: R2 е добър начин за решаване на проблема ви.


1 за отговор № 2

Рон Савидж от общността на Марпа излезе със следното:


моят ($ parser) = текст :: балансиран ::Marpa -> нов ( open => ["{"], close => ["}", );  my ($ text) = read_text ("policies.txt"); my ($ result) = $ parser -> разбор (текст => $ текст);  print "Разбор на резултата: $ result (0 е успех) n"; #print join ("n", @ {$ parser -> дърво -> tree2string}), "n";  ми ($ тире);  за моя $ node ($ parser -> tree -> траверс ($ parser -> дърво -> POST_ORDER)) { $ indent = "" x $ node -> дълбочина; $ text = $ {$ node -> meta} {текст} = ~ 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;

Това същност съдържа горния код и изход. Форматът на Stackoverflow настоява да се вмъкне всичко само, независимо дали го разбира или не - на същността може да се разчита да съдържа копие преди повреда.