2012-03-29 56 views
4

我成功地解析思科配置文件,並抓住每一個標記之間配置的部分(Cisco使用符號!)使用的多行正則表達式:Perl的正則表達式多行匹配到散列

/(search string)/i .. /^!/ 

我的代碼如下所示:

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 

my (@results, @data) ; 

#Test data to simulate a while loop on a file-handle running through a config file. 
@data = (
    "vlan 81" , 
    " name Vlan 81 test1" , 
    "!" , 
    "vlan 82" , 
    " name Vlan 82 test2" , 
    "!" , 
    "vlan 83" , 
    " name Vlan 83 test3" , 
    "!" 
); 

foreach (@data) { 
    if (/vlan/i .. /^!/) { 
     push (@results , $_) ;     
    } 
} 

print Dumper (@results) . "\n" ; 

exit; 

它的作品真的很好,但我要的結果推到一個哈希,用的代碼是一個匿名的陣列中的每個部分,所以結果看起來是這樣的:

%Vlan -> [Vlan 81, name Vlan 81 test1] , [Vlan 82, name Vlan 82 test2] , [Vlan 83, name Vlan 83 test3] 

但我不能解決如何做到這一點,我的代碼匹配搜索字符串和標記之間的每行,我最終將結果重建爲另一個數組,逐行。

任何幫助,非常感謝。

乾杯,

安迪

+0

你的目標不是那麼清楚,因爲你的例子已經有一個默認的鍵'Vlan'一個條目。對於這個鍵你有一個數組列表。你是不是指每個鍵(例如Vlan 81)都有散列值? – Matteo 2012-03-29 11:26:22

+0

是的,你說得對,謝謝你的評論,我會盡力在未來更加清晰。 – user1039417 2012-03-29 19:55:08

回答

4

我不知道你的意思的哈希什麼,因爲你的內容描述只是一個匿名數組列表。沒有鍵,所以你只能生成一個數組。如果你可以解釋哪部分數據是關鍵,那麼我們可以去做一個哈希。

use warnings附註優於0123bshebang修飾符,因爲它更靈活,可以否定。

範圍運算符..可能是可愛的,但你不能在任何可能的地方使用它。

將輸入分隔符設置爲"!\n"將允許您一次讀入所有相關行,然後將其插入到您的陣列中。

的代碼看起來像這樣

use strict; 
use warnings; 

use Data::Dumper; 

my @Vlan; 

$/ = "!\n"; 

while (<DATA>) { 
    chomp; 
    push @Vlan, [split /[\r\n]+/]; 
} 

print Data::Dumper->Dump([\@Vlan], ['*Vlan']); 

__DATA__ 
vlan 81 
name Vlan 81 test1 
! 
vlan 82 
name Vlan 82 test2 
! 
vlan 83 
name Vlan 83 test3 
! 

輸出

@Vlan = (
      [ 
      'vlan 81', 
      'name Vlan 81 test1' 
      ], 
      [ 
      'vlan 82', 
      'name Vlan 82 test2' 
      ], 
      [ 
      'vlan 83', 
      'name Vlan 83 test3' 
      ] 
     ); 

編輯

如果哈希的關鍵是始終記錄的第一線設置,然後這個程序產生,你要求

use strict; 
use warnings; 

use Data::Dumper; 

my %Vlan; 

$/ = "!\n"; 

while (<DATA>) { 
    chomp; 
    my ($k, $v) = split /[\r\n]+/; 
    $Vlan{$k} = $v; 
} 

print Data::Dumper->Dump([\%Vlan], ['*Vlan']); 

__DATA__ 
vlan 81 
name Vlan 81 test1 
! 
vlan 82 
name Vlan 82 test2 
! 
vlan 83 
name Vlan 83 test3 
! 

輸出

%Vlan = (
      'vlan 81' => 'name Vlan 81 test1', 
      'vlan 83' => 'name Vlan 83 test3', 
      'vlan 82' => 'name Vlan 82 test2' 
     ); 
+0

這正是我想要達到的目標,我會嘗試一下。也沒有意識到有多少特殊變量存在。謝謝您的幫助。 – user1039417 2012-03-30 08:54:08

2

這一個保持狀態的,而不是做多行:

my %Vlan; 

#Test data to simulate a while loop on a file-handle running through a config file. 
@data = (
    "vlan 81" , 
    " name Vlan 81 test1" , 
    "!" , 
    "vlan 82" , 
    " name Vlan 82 test2" , 
    "!" , 
    "vlan 83" , 
    " name Vlan 83 test3" , 
    "!" 
); 

foreach (@data) { 
    if (/ name (\w+ \d+) /) { 
     my $name = lc $1; 
     die("undef $name") if (not defined $Vlan{$name}); 
     $Vlan{$name} = [$name, $_]; 
    } elsif (/^(\w+ \d+)$/) { 
     my $name = lc $1; 
     $Vlan{$name}++; 
    } 
} 

print Dumper (%Vlan) . "\n" ; 

exit; 
3

變更程序的結束

my %Vlan; 

for (@data) { 
    if (my $inside = /vlan/i .. /^!/) { 
    if ($inside =~ /E0$/) { 
     s/^\s+//, s/\s+$// for @results; # trim whitespace 
     $Vlan{ $results[0] } = join ", ", @results; 
     @results =(); 
    } 
    else { 
     push @results, $_; 
    } 
    } 
} 

print Dumper \%Vlan; 

.. range operator回報與"E0"權當結尾的值的哈希手狀態爲真,所以我們可以使用它作爲何時將新條目放入的提示。

返回的值是false的空字符串或序列號(從1開始)爲true。對於遇到的每個範圍,都會重置序列號。範圍中的最後一個序列號附加了字符串"E0",該字符串不會影響其數字值,但會爲您提供搜索的信息,以查找是否要排除端點。

您的最終目標不明確,但您似乎希望散列值是字符串而不是數組。 Perl的join通過插入值列表中的元素之間的某個分隔符創建一個字符串。上面的代碼在使用@results中的每個值刪除前導空格和尾隨空格,然後使用它們填充%Vlan

輸出:

$VAR1 = { 
      'vlan 81' => 'vlan 81, name Vlan 81 test1', 
      'vlan 83' => 'vlan 83, name Vlan 83 test3', 
      'vlan 82' => 'vlan 82, name Vlan 82 test2' 
     };
+0

對E0感興趣,我已經忘記了這種行爲。我也會測試你的代碼。 – user1039417 2012-03-30 08:58:23