Perl:grep变量的唯一值

Perl:grep变量的唯一值,perl,Perl,我正在使用XML::Simple解析XML文件 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} .

我正在使用XML::Simple解析XML文件

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
在这里,我只想创造独特的价值观,但我已经尝试了很多东西,但似乎没有任何效果

我使用了以下方法

use List::MoreUtils qw(uniq);
my @unique = uniq $lanip;
还有这个

my @unique = do { my %seen; grep { !$seen{$_}++ } $lanip };
print $lanip . "\n" if !  $seen{$lanip}++  
还有这个

my @unique = do { my %seen; grep { !$seen{$_}++ } $lanip };
print $lanip . "\n" if !  $seen{$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);
  }
}

因为
$lanip
是一个标量变量而不是列表,所以这些都不起作用。您需要首先将其转换为列表:

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 , "";

请-不要使用
XML::Simple
。即使是它的医生也建议不要使用它

另外,您看起来就像是在将IP地址转换为网络地址,只需将0作为最后一个八位字节。这只适用于使用
/24
子网的情况,所以实际上,您不应该这样做

类似于
Net::IPv4Addr
的东西看起来可以为您计算该总和,从而为您提供一个合适的地址范围。(或者,如果您愿意的话,您也可以自己做位模式——您所做的只是位掩码和IP地址的逻辑AND。)

相反-猜测一下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 ); 

$lanip
是包含所有IP的字符串吗?你的问题不清楚。我假设它是,但根据代码示例,它似乎包含一个IP。您应该在数组上使用
uniq
,而不是字符串。例如:
perl-MList::MoreUtils=uniq-E'@a=qw(192.169.30.0192.169.30.0192.169.31.0);对uniq@a;说$u
如果
%seen
在循环之外声明:
my%seen;对于我的$server(@{$servers->{server}}){…
@melpomene
-我试过了,但不幸的是也不起作用。
#!/usr/bin/perl-w使用XML::Simple;my$servers=XMLin('network.XML');my%seen;foreach my$server(@{$servers->{server}}){my%seen;my$node=$server->{NodeName\n;my$lanip=$server->{CoreLanIP\u 1\u 1};my$mask=$server->{CoreLanNetmask\u 1}.\n;substr($lanip,11,3)=“0”;print$lanip.\n“if!$seen{$lanip}++}
@user55342您有
my%seen;
两次(外部的一次由于阴影而未使用)。删除内部声明。