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:
#!/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.