在Perl中将紧凑字符串反向转储到变量中

p8ekf7hl  于 8个月前  发布在  Perl
关注(0)|答案(2)|浏览(80)

我有一个这样的结构:

my %Tr106IPInterfaceXsListSyntax = (
      tr69InstanceId22079 => {type => 'INTEGER', Ordinal => 0},
      tr106IPv4AddressXsBifoldList_001 => {
        type => [
          { Tr106IPv4AddressXsBifoldListSyntax => {
            tr69InstanceId22082 => {type => 'INTEGER', Ordinal => 0},
            iPAddress21929 => {type => 'STRING', Ordinal => 1},
            subnetMask21930 => {type => 'STRING', Ordinal => 2},
            addressingType22310 => {type => 'ENUMERATION', Ordinal => 3}
            }
          }
        ],
        Ordinal => 1
      },       
      tr106IPv6AddressXsBifoldList_001 => {
         type => [
          { Tr106IPv6AddressXsBifoldListSyntax => {
            tr69InstanceId22330 => {type => 'INTEGER', Ordinal => 0},
            iPAddress22326 => {type => 'STRING', Ordinal => 1},
            origin22327 => {type => 'ENUMERATION', Ordinal => 2}
            }
          }
        ],
        Ordinal => 2
      },
      iPv4Enable22321 => {type => 'BOOLEAN', Ordinal => 3},
      status21926 => {type => 'ENUMERATION', Ordinal => 4},
      name22274 => {type => 'STRING', Ordinal => 5},
      lastChange21927 => {type => 'INTEGER', Ordinal => 6},
      lowerLayers22080 => {type => [ 'STRING' ], Ordinal => 7},
      type22309 => {type => 'ENUMERATION', Ordinal => 8},
      iPv4AddressNumberOfEntries21928 => {type => 'INTEGER', Ordinal => 9},
      iPv6AddressNumberOfEntries22322 => {type => 'INTEGER', Ordinal => 10},
      iPv6Enable22323 => {type => 'BOOLEAN', Ordinal => 11}
    );

从一个外部源,我得到一个这样的字符串:

"[{1,[{1,'10.16.195.16','255.255.254.0',DHCP}],[],true,UP,'',0,[''],NORMAL,1,0,false},{2,[{1,'10.15.128.69','255.255.255.255',IKEV2}],[],false,UP,'4g_core_tunnel',1,[''],TUNNEL,1,0,false}]"

或者同样的字符串

"[
  { 1, 
    [ {1, '10.16.195.16', '255.255.254.0', DHCP} ],
    [ ],
    true,
    UP,
    '',
    0,
    [''],
    NORMAL,
    1,
    0,
    false
  },
  { 2,
    [ {1, '10.15.128.69', '255.255.255.255', IKEV2 } ],
    [],
    false,
    UP,
    '4g_core_tunnel',
    1,
    [''],
    TUNNEL,
    1,
    0,
    false
   }
]"

如何将这个紧凑的字符串转换为像这样的可用变量:

my $var = [
   {
      tr69InstanceId22079 => 1,
      tr106IPv4AddressXsBifoldList_001 => [
         { 
            tr69InstanceId22082 => 1,
            iPAddress21929 => '10.16.195.16',
            subnetMask21930 => '255.255.254.0',
            addressingType22310 => "DHCP"
         }
      ],       
      tr106IPv6AddressXsBifoldList_001 => [],
      iPv4Enable22321 => "true",
      status21926 => "UP",
      name22274 => '',
      lastChange21927 => 0,
      lowerLayers22080 => [ '' ],
      type22309 => "NORMAL",
      iPv4AddressNumberOfEntries21928 => 1,
      iPv6AddressNumberOfEntries22322 => 0,
      iPv6Enable22323 => "false"
   },
   {
      tr69InstanceId22079 => 2,
      tr106IPv4AddressXsBifoldList_001 => [
         { 
            tr69InstanceId22082 => 1,
            iPAddress21929 => '10.15.128.69',
            subnetMask21930 => '255.255.255.255',
            addressingType22310 => "IKEV2"
         }
      ],       
      tr106IPv6AddressXsBifoldList_001 => [],
      iPv4Enable22321 => "false",
      status21926 => "UP",
      name22274 => '4g_core_tunnel',
      lastChange21927 => 1,
      lowerLayers22080 => [ '' ],
      type22309 => "TUNNEL",
      iPv4AddressNumberOfEntries21928 => 1,
      iPv6AddressNumberOfEntries22322 => 0,
      iPv6Enable22323 => "false"
   }   
]

在我的脚本中,我有大约30种不同的结构,所以最好是通用的(即动态的和最有可能递归的)解决方案。我想我必须组成一个正则表达式,然后逐个处理这些组。也许有一个模块可以做到这一点,我不必重新发明轮子。

2lpgd968

2lpgd9681#

这是一个两个阶段的问题。首先你必须把字符串转换成一个可行的perl结构。
假设你已经控制了你收到的数据,你可以使用eval。

use strict;
use warnings;
my $data_as_string = "[{1,[{1,'10.16.195.16','255.255.254.0',DHCP}],[],true,UP,'',0,[''],NORMAL,1,0,false},{2,[{1,'10.15.128.69','255.255.255.255',IKEV2}],[],false,UP,'4g_core_tunnel',1,[''],TUNNEL,1,0,false}]";

# Change {} into [] as we dont have the attributes ye
$data_as_string =~ s/\{/[/g;
$data_as_string =~ s/\}/]/g;

# Quote String constants.
$data_as_string =~ s/(?<=[,\[])(\w*[a-z]\w*)(?=[,\]])/'$1'/ig;

my $data = eval $data_as_string;

然后你必须重写结果并生成你的对象。最简单的方法是为每种类型写一个函数。

my @result;
foreach my $ele (@$data) {
    push @result, get_Tr106IPInterfaceXs( $ele);
}

sub get_Tr106IPInterfaceXs {
    my $array = shift;
    return 
    {
      tr69InstanceId22079 => $array->[0],
      tr106IPv4AddressXsBifoldList_001 => [
        map {get_tr106IPv4AddressXsBifold($_)} @{$array->[1]}
      ],       
      tr106IPv6AddressXsBifoldList_001 => $array->[2],
      iPv4Enable22321 => $array->[3],
      status21926 => $array->[4],
      name22274 => $array->[5],
      lastChange21927 => $array->[6],
      lowerLayers22080 => $array->[7],
      type22309 => $array->[8],
      iPv4AddressNumberOfEntries21928 => $array->[9],
      iPv6AddressNumberOfEntries22322 => $array->[10],
      iPv6Enable22323 => $array->[11]
    }
}

sub get_tr106IPv4AddressXsBifold {
    my $array = shift;
    return  { 
            tr69InstanceId22082 => $array->[0],
            iPAddress21929 => $array->[1],
            subnetMask21930 => $array->[2],
            addressingType22310 => $array->[3]
    }
}

添加

use Data::Dumper;
print Dumper \@result;

在最后,按预期打印出所有内容。

v1uwarro

v1uwarro2#

我问的问题与我的实际职责有点不同,但我想限制我的问题的范围。最后,我必须将所有这些数据插入到关系Oracle数据库中,因此并不真正需要在变量中具有完整的结构。
主要目标是只从给定的结构中导出所有内容。从结构中,我能够组成正则表达式。在这个例子中,它将是

  • \{(\d+),\[.*?],\[.*?],(true|false),(\w+),('.*?'),(\d+),(\[.*?]),(\w+),(\d+),(\d+),(true|false)}
  • \{(\d+),('.*?'),('.*?'),(\w+)}
  • \{(\d+),('.*?'),(\w+)}

然后我执行这些正则表达式并使用匹配。

use Data::Dumper;
    
my @result;
my $input = "[{1,[{1,'10.16.195.16','255.255.254.0',DHCP}],[],true,UP,'',0,[''],NORMAL,1,0,false},{2,[{1,'10.15.128.69','255.255.255.255',IKEV2}],[],false,UP,'4g_core_tunnel',1,[''],TUNNEL,1,0,false}]";

my @regex;
my @attr = sort { $Tr106IPInterfaceXsListSyntax{$a}{Ordinal} <=> $Tr106IPInterfaceXsListSyntax{$b}{Ordinal} } keys %Tr106IPInterfaceXsListSyntax;
foreach my $key ( @attr ) {
  if ( $Tr106IPInterfaceXsListSyntax{$key}{type} eq 'STRING' )   {
    push(@regex, "('.*?')");    
  } elsif ( $Tr106IPInterfaceXsListSyntax{$key}{type} eq 'BOOLEAN' )   {
    push(@regex, "(true|false)");
  } elsif ( $Tr106IPInterfaceXsListSyntax{$key}{type} eq 'INTEGER' )   {
    push(@regex, "(\\d+)");
  } elsif ( $Tr106IPInterfaceXsListSyntax{$key}{type} eq 'ENUMERATION' )   {
    push(@regex, "(\\w+)");
  } elsif ( ref($Tr106IPInterfaceXsListSyntax{$key}{type}) eq 'ARRAY' && $Tr106IPInterfaceXsListSyntax{$key}{type}[0] eq 'STRING' )   {
    push(@regex, "(\\[.*?])");
  } else {
    push(@regex, "\\[.*?]");
  }
}
my $regex = '\\{' . join(',', @regex) . '}';

while ( $input =~ m/$regex/g ) {
  my %Tr106IPInterface = {};
  foreach $pos (1..$#-) {
    $Tr106IPInterface{$attr[$pos-1]} = substr( $input, $-[$pos], $+[$pos] - $-[$pos]);
  }
  push(@result, \%Tr106IPInterface); 
  # ... do some more stuff with %Tr106IPInterface
}

print Dumper \@result;

嵌套结构在这段代码中还没有涉及,但是它显示了我将遵循的原则。

相关问题