Home > Archive > PERL Beginners > August 2007 > Trying to dynamically create arrays, getting can't use string as ARRAY ref
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Trying to dynamically create arrays, getting can't use string as ARRAY ref
|
|
| Justin The Cynical 2007-08-23, 7:59 am |
| Greets.
I have a 'config file' that contains a group name (alphanumeric) and
machine name/numbers separated by whitespace. Each group is on it's
own line. The file looks like this:
prod01 456 345 234
prod02 789 517 325
....etc, etc, etc...
What I am attempting to do is:
Put the file contents into an array
Pull the first entry off the array
Add the name of the array to a 'master array' list of the machine
groups
Then create another array, which would be referenced by the group
name, and contains the machines associated with the group.
Here is the code I have now that is giving me problems:
# parse the config file
foreach (@filelist){
# for each line of the config file, place the entries
# into a temp array
my @temp=split(/ /);
# pull the first entry off the array
my $group=shift(@temp);
# add the name of the array to the main rg array list
push (@grouplist, $group);
# push the rest of the entries into an array that has
# the same name as the rg in question
foreach (@temp){
push (@$group, $_);
}
}
The idea of the script as a whole is to take the config file and split
it into multiple arrays. Once that is done, connect to each machine
and pull some files into another directory.
The script flow:
-Read the config file, put each line into an array - @temp = qw {prod1
456 345 234}
-Pull the first value from the temp array ($grp) and place it into the
master list - @master = qw {'prod1 prod2}
-Create a new array on the fly (it needs to be this way as new groups
may be created, or old ones removed) with the name of the pulled value
($grp) and place the machine names/numbers into that array - @prod1 =
qw {456 345 234} @prod02 = qw {789 517 325} etc...
-Loop through the master list, using each value as the pointer to the
individual array that contains the machines
-Connect to each machine in turn and pull the files
The script runs if I do not use strict (which I consider a Bad
Thing). But when I run it with strict, I receive the following error:
Can't use string ("prod01") as an ARRAY ref while "strict refs" in use
Am I missing something really basic that is covered in the Llama (3rd
edition), and can anyone give me any hints?
| |
| Lists User 2007-08-23, 7:59 am |
| Hi,
Rather than a dynamic array,you just need to use a correct datastru,a hash.
It's maybe better to write codes as below.
[tmp]$ cat groups.txt
prod01 456 345 234
prod02 789 517 325
prod03 789 517 325
prod04 789 517 325
prod05 789 517 325
[tmp]$ cat test.pl
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %grouplist;
open HD,'groups.txt' or die $!;
while(<HD> ) {
chomp;
my @tmp = split;
my $groupname = shift @tmp;
$grouplist{$groupname} = [@tmp];
}
close HD;
print Dumper \%grouplist;
__END__
[tmp]$ perl test.pl
$VAR1 = {
'prod04' => [
'789',
'517',
'325'
],
'prod05' => [
'789',
'517',
'325'
],
'prod01' => [
'456',
'345',
'234'
],
'prod03' => [
'789',
'517',
'325'
],
'prod02' => [
'789',
'517',
'325'
]
};
Do you know how to loop through a hash?If not,please write back to the list.
2007/8/23, Justin The Cynical <jdcynical@gmail.com>:
> Greets.
>
> I have a 'config file' that contains a group name (alphanumeric) and
> machine name/numbers separated by whitespace. Each group is on it's
> own line. The file looks like this:
>
> prod01 456 345 234
> prod02 789 517 325
> ...etc, etc, etc...
>
> What I am attempting to do is:
> Put the file contents into an array
> Pull the first entry off the array
> Add the name of the array to a 'master array' list of the machine
> groups
> Then create another array, which would be referenced by the group
> name, and contains the machines associated with the group.
>
> Here is the code I have now that is giving me problems:
>
> # parse the config file
> foreach (@filelist){
>
> # for each line of the config file, place the entries
> # into a temp array
> my @temp=split(/ /);
>
> # pull the first entry off the array
> my $group=shift(@temp);
>
> # add the name of the array to the main rg array list
> push (@grouplist, $group);
>
> # push the rest of the entries into an array that has
> # the same name as the rg in question
> foreach (@temp){
> push (@$group, $_);
> }
> }
>
> The idea of the script as a whole is to take the config file and split
> it into multiple arrays. Once that is done, connect to each machine
> and pull some files into another directory.
>
> The script flow:
> -Read the config file, put each line into an array - @temp = qw {prod1
> 456 345 234}
>
> -Pull the first value from the temp array ($grp) and place it into the
> master list - @master = qw {'prod1 prod2}
>
> -Create a new array on the fly (it needs to be this way as new groups
> may be created, or old ones removed) with the name of the pulled value
> ($grp) and place the machine names/numbers into that array - @prod1 =
> qw {456 345 234} @prod02 = qw {789 517 325} etc...
>
> -Loop through the master list, using each value as the pointer to the
> individual array that contains the machines
>
> -Connect to each machine in turn and pull the files
>
> The script runs if I do not use strict (which I consider a Bad
> Thing). But when I run it with strict, I receive the following error:
>
> Can't use string ("prod01") as an ARRAY ref while "strict refs" in use
>
> Am I missing something really basic that is covered in the Llama (3rd
> edition), and can anyone give me any hints?
>
>
> --
> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
> For additional commands, e-mail: beginners-help@perl.org
> http://learn.perl.org/
>
>
>
| |
| Paul Lalli 2007-08-23, 7:59 am |
| On Aug 23, 2:00 am, jdcyni...@gmail.com (Justin The Cynical) wrote:
> Add the name of the array to a 'master array' list of the machine
> groups
> Then create another array, which would be referenced by the group
> name, and contains the machines associated with the group.
> The script runs if I do not use strict (which I consider a Bad
> Thing). But when I run it with strict, I receive the following error:
>
> Can't use string ("prod01") as an ARRAY ref while "strict refs" in use
perldoc -q "variable name"
> Am I missing something really basic that is covered in the Llama (3rd
> edition),
No, because it's not basic. You should be using a multi-dimensional
structure, as Lists User recommended. Rather than storing the name of
an array, store the name of a key to your hash of arrays, and let the
value be a reference to an anonymous array.
my %array_named;
$array_named{foo} = [ 1, 2, 3, 4];
$array_named{bar} = [qw/ alpha beta gamma delta/];
for my $name (keys %array_named) {
print "$name: @{$array_named{$name}}\n";
}
See also:
perldoc perlreftut
perldoc perllol
perldoc perldsc
Hope that helps,
Paul Lalli
| |
| Justin The Cynical 2007-08-24, 7:59 am |
| On Aug 23, 2:00 am, practicalp...@gmail.com (Lists User) wrote:
*snip*
> my %grouplist;
> open HD,'groups.txt' or die $!;
>
> while(<HD> ) {
> chomp;
> my @tmp = split;
> my $groupname = shift @tmp;
> $grouplist{$groupname} = [@tmp];}
>
> close HD;
OK, thanks!
The Llama presents hashes as single value to a key, so I never thought
to make a hash of arrays.
Here is what I am using, and I think my comments are correct on how it
works:
while (<CONFIG> ) {
# Remove any extra carriage returns
chomp;
# for each line of the config file, place the entries
# into a temp array
my @temp = split;
# pull the first entry, which is the group name, and put it
into
# the variable $groupname to be used when creating the
'master' list
my $groupname = shift @temp;
# Create the hash named grouplist. Each key is the value of
$groupname. The values
# of the key are what is left of the line we are working with
contained in
# the array @temp
$grouplist{$groupname} = [@temp];
}
# Close the file handle on the config file
close CONFIG;
> Do you know how to loop through a hash?If not,please write back to the list.
Yes and no.
I did some searching and found the following. I think I understand
most of it, I'm just not 100% clear on the 'for my' loops.
Or should I say that I understand them enough to lift the code from
the example and make it work with my script, but don't fully
understand the logic behind it. :-)
for my $foo ( keys %grouplist ){
*directory check/create code*
# File Pull loop
# This creates a temp variable named i. It is used as a
counter
# to tell the loop which entry in the array to pull the vru
# number from. The $# gets the number of the last value of
the
# referenced array and uses it as the number of times to run
# through the loop as well as the index for the array.
for my $i ( 0 .. $#{ $grouplist{$groupname} } ) {
*file pull code*
}
}
Thank you everyone, this has been very helpful!
| |
| Justin The Cynical 2007-08-24, 7:59 am |
| On Aug 23, 3:42 am, mri...@gmail.com (Paul Lalli) wrote:
> On Aug 23, 2:00 am, jdcyni...@gmail.com (Justin The Cynical) wrote:
*snip*
>
> perldoc -q "variable name"
Ah, OK, thanks. I've got a bit of reading to do. :-)
>
> No, because it's not basic. You should be using a multi-dimensional
> structure, as Lists User recommended. Rather than storing the name of
> an array, store the name of a key to your hash of arrays, and let the
> value be a reference to an anonymous array.
Oh good, I'm not missing something obvious then.
I have redone the code and posted it for comprehension purposes. And
after testing the script, it does seem to run a bit quicker than the
original using arrays alone.
*snip*
> See also:
> perldoc perlreftut
> perldoc perllol
> perldoc perldsc
>
> Hope that helps,
> Paul Lalli
It does, thank you again Paul.
| |
| Jeff Pang 2007-08-24, 7:59 am |
| 2007/8/24, Justin The Cynical <jdcynical@gmail.com>:
> On Aug 23, 2:00 am, practicalp...@gmail.com (Lists User) wrote:
>
> *snip*
>
>
> Yes and no.
>
Hi,
practicalperl's solution is right.He/she created a correct datastru for you.
This is the general way to loop through that hash,
for my $key (keys %grouplist) {
print "groupname: ", $key,"\n";
print "group content: ", "@{$grouplist{$key}}" ,"\n";
}
Because $grouplist{$key} is an anonymous array,so you need to
dereference it,saying @{
$grouplist{$key}} would do that.
All you need is to read 'perldoc perldata'.
Good luck!
| |
| Randal L. Schwartz 2007-08-24, 7:01 pm |
| >>>>> "Justin" == Justin The Cynical <jdcynical@gmail.com> writes:
Justin> The Llama presents hashes as single value to a key, so I never thought
Justin> to make a hash of arrays.
That's because (a) an arrayref is still a single value, so we haven't really
lied, so much as just simplified to what can be handled in the first 30 hours
with Perl, and (b) you *still* can't make a hash of arrays, just a hash of
arrayrefs, and that distinction is *important*.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
| |
| Justin The Cynical 2007-08-26, 8:01 am |
| On Aug 24, 9:11 am, mer...@stonehenge.com (Randal L. Schwartz) wrote:
>
> Justin> The Llama presents hashes as single value to a key, so I never thought
> Justin> to make a hash of arrays.
>
> That's because (a) an arrayref is still a single value, so we haven't really
> lied, so much as just simplified to what can be handled in the first 30 hours
> with Perl, and (b) you *still* can't make a hash of arrays, just a hash of
> arrayrefs, and that distinction is *important*.
Ok, so it's not an array that is in the hash, but a "symlink" (which
is a single value) to an actual array that lives in memory alone and
has no real reference outside of the hash, correct?
| |
| Peter Scott 2007-08-26, 7:01 pm |
| On Sun, 26 Aug 2007 01:00:31 +0000, Justin The Cynical wrote:
> On Aug 24, 9:11 am, mer...@stonehenge.com (Randal L. Schwartz) wrote:
>
> Ok, so it's not an array that is in the hash, but a "symlink" (which
> is a single value) to an actual array that lives in memory alone and
> has no real reference outside of the hash, correct?
Don't use the term "symlink", however tempting, or you'll confuse
yourself and others about real symlinks. Yes, it's not an array in the
hash; it's a scalar containing a *reference* to an array, and there may or
may not be other references to that array elsewhere in the program
depending on how the reference was constructed (with the anonymous
arrayref constructor or with the reference to a named array).
--
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/
| |
| Peter Scott 2007-08-26, 7:01 pm |
| On Sun, 26 Aug 2007 12:17:49 -0400, Mr. Shawn H. Corey wrote:
> Peter Scott wrote:
>
> Even anonymous arrays can be accessed from more than one place.
Right. I phrased that badly. The poster appeared to be wondering whether
there could be another reference to the array already in existence at the
time the arrayref was created in the hash and that was what I had in mind.
--
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/
| |
| Justin The Cynical 2007-08-30, 3:59 am |
| Ok, I think I more or less have it. The true grocking of the hash,
well, that I think will come in time with reading and experience.
Thank you all for the help and pointers!
Justin
|
|
|
|
|