2015-09-13 51 views
0

我使用XML :: Simple來分析xml文件。Perl:來自變量的grep唯一值

my $servers = XMLin('file.xml'); 
for my $server (@{$servers->{server}}) { 
    my %seen =(); 
    my $node = $server->{NodeName} . "\n"; 
    my $lanip = $server->{LanIP} . "\n"; 
    my $mask = $server->{Netmask} . "\n"; 

    substr($lanip, 11, 3) = "0"; 
    print "$lanip\n"; 
} 

的輸出這裏是像下面

192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.31.0 
192.169.31.0 
192.169.31.0 
192.169.32.0 
192.169.72.0 
192.169.72.0 
192.169.72.0 
192.169.32.0 
192.169.32.0 

在這裏,我只希望到grep獨特的價值觀,但我已經嘗試了很多事情,但似乎沒有任何工作。

我用下面的方法

use List::MoreUtils qw(uniq); 
my @unique = uniq $lanip; 

也是這個

my @unique = do { my %seen; grep { !$seen{$_}++ } $lanip }; 

也是這個

print $lanip . "\n" if ! $seen{$lanip}++ 

是否有人可以幫助我在這裏。

+0

'$ lanip'是一個包含所有IP的字符串嗎?目前尚不清楚你的問題。我認爲它是根據代碼示例,它似乎包含一個IP。 –

+0

您應該在數組上使用'uniq',而不是字符串。例如:'perl -MList :: MoreUtils = uniq -E'@ a = qw(192.169.30.0 192.169.30.0 192.169.31.0);說$ _ for uniq @a;'' –

+1

如果'%seen'被聲明在循環之外,那麼你最後的嘗試應該可以工作:'my%seen;爲我的$服務器(@ {$服務器 - > {服務器}}){...' – melpomene

回答

0

我會建議使用哈希地圖,找到獨特的價值觀:

因爲 $lanip那些工作
#Let's count how many times each ip occures in a list  
%ip_count; 
for $ip (@ips) { 
    if (not defined $ip_count{$ip}) { 
    $ip_count{$ip} = 1; 
    } 
    else { 
    $ip_count{$ip}++; 
    } 
} 

# Now we need to filter unique ips 
@unique_ips; 
for $ip (keys(%ip_count)) { 
    if ($ip_count{$ip} == 1) { 
    push(@unique_ips, $ip); 
    } 
} 
0

沒有一個是標量,而不是一個列表。你需要先將其轉換成一個列表:

use List::MoreUtils qw(uniq); 
my $lanip="192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.30.0 
192.169.31.0 
192.169.31.0 
192.169.31.0 
192.169.32.0 
192.169.72.0 
192.169.72.0 
192.169.72.0 
192.169.32.0 
192.169.32.0"; 

my @unique=uniq split(/\n/,$lanip); 
print "@unique\n"; 

或者打印在單獨的行的每個唯一IP:

print join "\n", @unique , ""; 
0

請請請 - 不要使用XML::Simple。即使是文檔,也建議不要使用它。

另外 - 你看起來就像你正在轉換你的IP地址到一個網絡地址,只是堅持一個零作爲最後一個八位字節。那只有工程,如果你使用/24子網,真的 - 你不應該這樣做。

Net::IPv4Addr這樣的東西看起來像它爲你做的那樣,給你一個適當的地址範圍。 (或者你可以自己做位模式,如果你是這樣的傾向 - 所有你正在做的是邏輯位掩碼和IP地址和。)

相反 - 在你的XML結構猜測一下:

#!/usr/bin/env perl 

use strict; 
use warnings; 
use XML::Twig; 

my %seen; 

my $twig = XML::Twig -> parsefile ('file.xml'); 
foreach my $server ($twig -> findnodes ('//server')) { 
    my $lanip = $server->first_child_text('LanIP'); 
    my $mask = $server->first_child_text('Netmask'); 
    my ($net) = Net::IPv4Addr::ipv4_network("$lanip/$mask" 
    $seen{$net}++; 
} 

print join ("\n", sort keys %seen);