Perl 在哈希的哈希中搜索重复项

Perl 在哈希的哈希中搜索重复项,perl,multidimensional-array,hashmap,Perl,Multidimensional Array,Hashmap,我无法在心里解决这个问题,这对我来说太多了,也许有人可以帮助我: @Hosts = ("srv1","db1","srv2","db3","srv3","db3","srv3","db4","srv3","db5"); my $count = @Hosts; $count= $count / 2; my %hash; $i = 0; $ii = 1; $j = 0; $jj = 0; while ($jj < $count) { $hash{$j}{$Hosts[$i]} = $Hos

我无法在心里解决这个问题,这对我来说太多了,也许有人可以帮助我:

@Hosts = ("srv1","db1","srv2","db3","srv3","db3","srv3","db4","srv3","db5");
my $count = @Hosts;
$count= $count / 2;

my %hash;
$i = 0;
$ii = 1;
$j = 0;
$jj = 0;

while ($jj < $count) {
$hash{$j}{$Hosts[$i]} = $Hosts[$ii];

$i = $i + 2;
$ii = $ii +2;

$j++;
$jj++
}

print Dumper(\%hash);
我知道这段代码很难看,我不知道如何做得更好,我需要做的是找到双服务器和双数据库,然后把位置和重复的字符串放在一个数组或类似的东西中,我想从中生成一个Nagvis映射文件

Icinga配置文件包含如下am成员字符串:

while ($jj < $anzahl) {
    $hash{$j}{$Hosts[$i]} = $Hosts[$ii];

    $i = $i + 2;
    $ii = $ii +2;

    $j++;
    $jj++
 }
成员srv1、db1、srv2、db3、srv3、db3、srv3、db3、srv4

它有对server、db、server、db,下面是Nagvis配置的示例:

define host {
object_id=5e78fb
host_name=srv1
x=237
y=122
}

define service {
object_id=30646e
host_name=srv1
service_description=db1
x=52
y=122
}

define host {
object_id=021861
host_name=srv2
x=237
y=217
}

define service {
object_id=a5e725
host_name=srv1
service_description=db2
x=52
y=217
}

提前感谢

您需要明确说明您想要什么。根据你的描述很难判断

而且,您的代码处于非常糟糕的状态。缩进循环和if语句,如下所示:

while ($jj < $anzahl) {
    $hash{$j}{$Hosts[$i]} = $Hosts[$ii];

    $i = $i + 2;
    $ii = $ii +2;

    $j++;
    $jj++
 }
如果
使用strict
,则必须使用
my
声明所有变量。这可以确保您不会在一个位置使用
@array
,而在另一个位置使用
@Hosts
。这两行将捕获大约90%的错误


我不知道您是想要一个连接到各种服务器的所有DB系统的列表,还是想要一个连接到DB系统的各种服务器的列表。所以,我给你们两个

我猜您的
@array
是一个列表,其中列出了您的所有计算机和数据库:

use strict;
use warnings;
use feature qw(say);   # Allows me to use "say" instead of "print"
use Data::Dumper;

my @systems = qw(      # The qw(...) is like putting quotes around each word.
    svr1  db1          # A nice way to define an array...
    srv2  db3
    srv3  db3
    srv3  db4
    srv3  db5
);

my %db_systems;       # Database systems with their servers.
my %servers;          # Servers with their database systems.


for (;;) {            # Loop forever (until I say otherwise)
    my $server   = shift @systems;

    #
    # Let's check to make sure that there's a DB machine for this server
    #

    if ( not @systems ) {
       die qq(Cannot get database for server "$server". Odd number of items in array);
    }

    my $database = shift @systems;

    $servers{$server}->{$database}    = 1;
    $db_systems{$database}->{$server} = 1;
    last if not @systems;    # break out of loop if there are no more systems
}

say "Servers:" . Dumper \%servers;
say "Databases: " . Dumper \%db_systems;
这将产生:

Servers:$VAR1 = {
        'srv3' => {
                    'db4' => 1,
                    'db3' => 1,
                    'db5' => 1
                    },
        'svr1' => {
                    'db1' => 1
                    },
        'srv2' => {
                    'db3' => 1
                    }
        };

Databases: $VAR1 = {
        'db4' => {
                    'srv3' => 1
                },
        'db3' => {
                    'srv3' => 1,
                    'srv2' => 1
                },
        'db5' => {
                    'srv3' => 1
                },
        'db1' => {
                    'svr1' => 1
                }
        };
这接近你想要的吗


补遗
嗨,这是工作!!现在我需要了解如何访问这些值以在文件中打印它们。这种乱七八糟的东西有点让我讨厌。谢谢你的快速帮助

您需要阅读关于的Perl教程和关于参考的Perl教程

在Perl中,所有数据都是标量数据,这意味着变量谈论的是单个值。在其他编程语言中,有结构或记录,但没有Perl

甚至数组和散列也不过是单个数据位的集合。当你需要更复杂的东西时会发生什么

引用是另一个Perl数据结构的内存位置。您可以引用标量变量,如
$foo
,但在大多数情况下,这对您没有多大好处。当您有一个指向数组或散列的引用时,这会有所帮助。通过这种方式,可以使用更复杂的结构来表示这些数据

想象一个由十项组成的数组(
$foo[0]
$foo[9]
)。数组中的每个条目都指向另一个包含十项的数组。现在这里引用了101个单独的数组。我们可以将它们视为单个结构,但重要的是要记住它们是独立的数组

我在
$foo[0]
中引用了一个数组。如何访问阵列本身?我做的就是所谓的去引用。为了做到这一点,我使用了前面有右标志的花括号。(符号是您在Perl变量前面看到的
$
@
%

$foo[0];                   # Reference to an array
my @temp = @{ $foo[0] };   # Dereferencing.
my $temp[0];               # Now I can access that inner array
每次必须取消引用时都必须使用临时数组,这相当笨拙,因此我不必:

$foo[0];                     # Reference to an array
my $value = ${ $foo[0] }[0]; # Getting the value of an item in my array reference
你可以看到最后一个有点难读。想象一下,如果我有一个项目数组的散列:

my $phone = ${ ${ ${ $employee{$emp_number} }{phone} }[0] }{NUMBER};
这有点笨拙。幸运的是,Perl允许您使用一些快捷方式。首先,我可以嵌套引用并使用默认优先级:

my $phone = $employee{$emp_number}{phone}[0]{NUMBER};
我更喜欢使用
->
符号:

my $phone = $employee{$emp_number}->{phone}->[0]->{NUMBER};
箭头概念更清晰,因为它将各部分分开,并提醒您这些是引用!.and,而不是一些复杂的结构数据结构。这有助于提醒您何时必须执行取消引用,例如当您使用
弹出
推送
命令时:

for my $field ( keys %{ $employee } ) {  # Dereference the hash
   say "Field $field = " . $employee{$emp_number}->{$field}
      if ( not ref $employee{$emp_number}->{$field} );
}
查找,查看它的作用以及为什么我只对打印出
ref
返回空字符串的字段感兴趣

现在,您应该能够看到如何使用
->
语法访问哈希:

my $db_for_server = $servers{$server}->{$database};
您可以使用两个循环:

for my $server ( keys %servers } {
    my %db_systems = %{ $servers{$server} };  # Dereferencing
    for my $db_system ( keys %db_systems } {
       say "Server $server has a connection to $db_systems{$db_system}";
    }
}
或者,没有中间哈希

for my $server { keys %servers } {
    for my $db_system ( keys %{ $servers{$server} } ) {
        say "Server $server has a connection to " . $servers{$server}->{$db_system};
    }
}

现在,到那里去找一本好的书。你需要学习好的编程技巧,比如使用好的变量名、缩进、使用strict和warning,以帮助你编写更好的程序,更容易理解和支持。

你能不能只显示示例输入和输出?你的同事不清楚定义您实际想要得到的内容。您不应该使用变量名,如
$i
$ii
。而是使用说明它们要做什么的描述性名称。此外,您的代码没有做任何我能看到的有意义的事情。首先,while循环不会运行,因为
$anzahl
未定义(在数字上下文中将变为
0
)它将看到
$jj<0
并失败。其次,您没有
@Hosts
数组,也没有分配任何内容给它。第三,您的
@array
数组只包含一个元素:双引号字符串。您好,sry我编辑了我的代码。数组的内容是可变的,它从文件中获取其元素,我必须在其中放入一些示例内容。什么你是说双重吗?你的意思是重复吗?
@array
应该代表什么?这些是机器名吗?
@Hosts
定义在哪里?很难说出你想要什么和你在做什么。我建议你展示包含重复项的示例数据,以及你想要的相应NagVis输出文件两者都需要。这很好,我会测试这个,非常感谢你们的快速帮助,真的很好!!!嗨,这很有效!!现在我需要了解如何访问值以在我的文件中打印它们。这个散列的东西对mee来说有点不公平。谢谢你们的快速帮助!
for my $server { keys %servers } {
    for my $db_system ( keys %{ $servers{$server} } ) {
        say "Server $server has a connection to " . $servers{$server}->{$db_system};
    }
}