简体   繁体   中英

Need help to populate a structs array in perl

I need some help to populate an array made of structs in perl.

The data for the array comesfrom a.SH file with the following format:

108,Country,Location,ap17,ip_149,ssh,model,12/8/2020

The code I am using is as follows:

use strict;
use warnings;
use Class::Struct;

struct(Net_Node => [hostname => '$', dir_ip => '$', access => '$', user => '$', pass => '$']);

my $node = Net_Node->new();
my @nodes;

my $user = "hjack";
my $pass = 'butstalion';

my $line;
my @all;

my $counter=0;

open(my $fh, '<', "exaple.sh") or die "Failed to open especified file";
#system('clear');

foreach $line (<$fh>) {

        @all=split(',', $line);


        $node->hostname ($all[3]);
        $node->dir_ip ($all[4]);
        $node->access ($all[5]);
        $node->user ($user);
        $node->pass ($pass);

        $nodes[$counter] = $node;

        $counter++;
}

my $size = @nodes;

print "\n \n";
print ("array size = $size\n\n");
$counter = 0;

while ($counter < 20) {
        print ($counter,"\n\n");    
        print ($nodes[$counter]->hostname,"\n");
        print ($nodes[$counter]->dir_ip, "\n");
        print ($nodes[$counter]->access, "\n");
        print ($nodes[$counter]->user, "\n");
        print ($nodes[$counter]->pass, "\n\n");

        $counter++;
}

close($fh);

The output of this code is a populated array but only with the last element generated in the foreach loop, is there any way to populate this array with the data of the.SH file?

Thanks in advance

the data of the file is as follows

89,Country,Location,sw01,ip_10,ssh,model,12/8/2020
90,Country,Location,sw02,ip_18,ssh,model,12/8/2020
91,Country,Location,sw03,ip_26,ssh,model,12/8/2020
92,Country,Location,sw04,ip_27,ssh,model,12/8/2020
93,Country,Location,sw05,ip_28,ssh,model,12/8/2020
94,Country,Location,sw06,ip_29,ssh,model,12/8/2020
95,Country,Location,ap02,ip_13,ssh,model,12/8/2020
96,Country,Location,ap03,ip_12,ssh,model,12/8/2020
97,Country,Location,ap04,ip_20,ssh,model,12/8/2020
98,Country,Location,ap05,ip_14,ssh,model,12/8/2020
99,Country,Location,ap06,ip_15,ssh,model,12/8/2020
100,Country,Location,ap07,ip_16,ssh,model,12/8/2020
101,Country,Location,ap08,ip_17,ssh,model,12/8/2020
102,Country,Location,ap09,ip_18,ssh,model,12/8/2020
103,Country,Location,ap10,ip_19,ssh,model,12/8/2020
104,Country,Location,ap11,ip_24,ssh,model,12/8/2020
105,Country,Location,ap12,ip_25,ssh,model,12/8/2020
106,Country,Location,ap14,ip_27,ssh,model,12/8/2020
107,Country,Location,ap15,ip_37,ssh,model,12/8/2020
108,Country,Location,ap17,ip_149,ssh,model,12/8/2020
my $node = Net_Node->new();
...
foreach $line (<$fh>) {
   ...
   $nodes[$counter] = $node;
}

creates a single Net_Node instance and overwrites its data in every iteration of the foreach loop. It sounds like you want to create a new instance for each line of the loop. So you should move your Net_Node->new() call inside the loop.

foreach $line (<$fh>) {
   my $node = Net_Node->new();
   ...
   $nodes[$counter] = $node;
}

With a simpler data structure like a native Perl hash, you could have appended a copy of the data structure to your list like

   $nodes[$counter] = { %$node };

but I would be more reluctant to do that with an object, which might not even be represented internally as a hash reference.

Perhaps the code could be implemented in the following shape

Comment:

  • define structure of node
  • for readability define an array with descriptive fields of interest
  • read file line by line
  • place temporary the data of interest into a hash
  • create a new node on each iteration
  • fill the node with data from hash
  • store the node in an array
  • generate an output for nodes data
#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4

use strict;
use warnings;
use feature 'say';

use Class::Struct Net_Node => [
        hostname    => '$',
        dir_ip      => '$',
        access      => '$',
        user        => '$',
        pass        => '$'
    ];

my @fields      = qw/hostname dir_ip access/;
my($user,$pass) = qw/hjack bustalion/;
my @nodes;

while( <DATA> ) {
    next if /^$/;                    # skip empty lines
    chomp;
    
    my %data;
    my $node = new Net_Node;

    @data{@fields} = (split(',',$_))[3..5];

    $node->hostname( $data{hostname} );
    $node->dir_ip( $data{dir_ip} );
    $node->access( $data{access} );
    $node->user( $user );
    $node->pass( $pass );

    push @nodes, $node;
}

say "\nTotal nodes = " . @nodes;
my $counter = 10;

for my $node ( @nodes ) {
    last unless $counter--;
    say "
    Hostname : " . $node->hostname . "
    Dir_IP   : " . $node->dir_ip   . "
    Access   : " . $node->access   . "
    Userid   : " . $node->user     . "
    Passwd   : " . $node->pass;
}

__DATA__
89,Country,Location,sw01,ip_10,ssh,model,12/8/2020
90,Country,Location,sw02,ip_18,ssh,model,12/8/2020
91,Country,Location,sw03,ip_26,ssh,model,12/8/2020
92,Country,Location,sw04,ip_27,ssh,model,12/8/2020
93,Country,Location,sw05,ip_28,ssh,model,12/8/2020
94,Country,Location,sw06,ip_29,ssh,model,12/8/2020
95,Country,Location,ap02,ip_13,ssh,model,12/8/2020
96,Country,Location,ap03,ip_12,ssh,model,12/8/2020
97,Country,Location,ap04,ip_20,ssh,model,12/8/2020
98,Country,Location,ap05,ip_14,ssh,model,12/8/2020
99,Country,Location,ap06,ip_15,ssh,model,12/8/2020
100,Country,Location,ap07,ip_16,ssh,model,12/8/2020
101,Country,Location,ap08,ip_17,ssh,model,12/8/2020
102,Country,Location,ap09,ip_18,ssh,model,12/8/2020
103,Country,Location,ap10,ip_19,ssh,model,12/8/2020
104,Country,Location,ap11,ip_24,ssh,model,12/8/2020
105,Country,Location,ap12,ip_25,ssh,model,12/8/2020
106,Country,Location,ap14,ip_27,ssh,model,12/8/2020
107,Country,Location,ap15,ip_37,ssh,model,12/8/2020
108,Country,Location,ap17,ip_149,ssh,model,12/8/2020

Output

Total nodes = 20

        Hostname : sw01
        Dir_IP   : ip_10
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : sw02
        Dir_IP   : ip_18
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : sw03
        Dir_IP   : ip_26
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : sw04
        Dir_IP   : ip_27
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : sw05
        Dir_IP   : ip_28
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : sw06
        Dir_IP   : ip_29
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : ap02
        Dir_IP   : ip_13
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : ap03
        Dir_IP   : ip_12
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : ap04
        Dir_IP   : ip_20
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

        Hostname : ap05
        Dir_IP   : ip_14
        Access   : ssh
        Userid   : hjack
        Passwd   : bustalion

Otherwise a slightly different approach can be taken to achieve similar result without Class::Struct module

#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4

use strict;
use warnings;
use feature 'say';

my @fields      = qw/hostname dir_ip access/;
my($user,$pass) = qw/hjack bustalion/;
my @nodes;

while( <DATA> ) {
        next if /^$/;
        chomp;

        my $node;
        $node->@{@fields} = (split(',',$_))[3..5];
        $node->@{qw/user pass/} = ($user, $pass);

        push @nodes, $node;
}

say "\nTotal nodes = " . @nodes;

for my $node ( @nodes ) {
    say "
        Hostname : " . $node->{hostname} . "
        Dir_IP   : " . $node->{dir_ip}   . "
        Access   : " . $node->{access}   . "
        Userid   : " . $node->{user}     . "
        Passwd   : " . $node->{pass};
}

__DATA__
89,Country,Location,sw01,ip_10,ssh,model,12/8/2020
90,Country,Location,sw02,ip_18,ssh,model,12/8/2020
91,Country,Location,sw03,ip_26,ssh,model,12/8/2020
92,Country,Location,sw04,ip_27,ssh,model,12/8/2020
93,Country,Location,sw05,ip_28,ssh,model,12/8/2020
94,Country,Location,sw06,ip_29,ssh,model,12/8/2020
95,Country,Location,ap02,ip_13,ssh,model,12/8/2020
96,Country,Location,ap03,ip_12,ssh,model,12/8/2020
97,Country,Location,ap04,ip_20,ssh,model,12/8/2020
98,Country,Location,ap05,ip_14,ssh,model,12/8/2020
99,Country,Location,ap06,ip_15,ssh,model,12/8/2020
100,Country,Location,ap07,ip_16,ssh,model,12/8/2020
101,Country,Location,ap08,ip_17,ssh,model,12/8/2020
102,Country,Location,ap09,ip_18,ssh,model,12/8/2020
103,Country,Location,ap10,ip_19,ssh,model,12/8/2020
104,Country,Location,ap11,ip_24,ssh,model,12/8/2020
105,Country,Location,ap12,ip_25,ssh,model,12/8/2020
106,Country,Location,ap14,ip_27,ssh,model,12/8/2020
107,Country,Location,ap15,ip_37,ssh,model,12/8/2020
108,Country,Location,ap17,ip_149,ssh,model,12/8/2020

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM