The problem is that I am trying to create a hash of hashes and then add more elements to each hash. I am reading from a file and im matching various items and I want to store them in a different subhash - ('Category', 'Item', 'Description', 'Score'). Later I will need to store them in a CSV file but at the moment I am just trying to print them, but I am getting a lot of errors.
Here is my code:
use strict;
use warnings;
my %MacroA = ('Category', 'Item', 'Description', 'Score');
open (my $file, '<', 'Layout.txt') or die $!;
while (my $line = <$file>) {
if ($line =~ /\b(layout)\b,/) {
$MacroA{Category}++;
}
elsif ($line =~ /,([\w\s]+?),/) {
$MacroA{Item}++;
}
elsif ($line =~ /,\b(\w+?.\d+?)\b,/g) {
$MacroA{Desciption}++;
}
elsif ($line =~ /,\b(pass|fail)\b/) {
$MacroA{Score}++;
}
}
close $file;
foreach my $categories (keys %{ $MacroA{$Category}}) {
print $categories, "\n";
}
foreach my $items (keys %{ $MacroA{$Item}}) {
print $items, "\n";
}
foreach my $descriptions (keys %{ $MacroA{$Description}}) {
print $descriptions, "\n";
}
foreach my $scores (keys %{ $MacroA{$Score}}) {
print $scores, "\n";
}
and the errors i get:
Global symbol "$Category" requires explicit package name at MacroA.pl line 29.
Global symbol "$Item" requires explicit package name at MacroA.pl line 32.
Global symbol "$Description" requires explicit package name at MacroA.pl line 35.
Global symbol "$Score" requires explicit package name at MacroA.pl line 38.
Execution of MacroA.pl aborted due to compilation errors. . .
Your issues simply represent a few basic missunderstandings that any programming beginner ends up struggling through. The comments are completely correct: when this sort of thing happens, read your errors and try to make sense of them using a few good tutorials or books. I'll have a go at helping you, although I don't quite know what you are trying to achieve.
You say you want to create a "hash of hashes" but by the looks of your code you are simply creating a counting hash, where you are keeping track of the number of times each of your first level "keys" (Category, Item, etc.) occurs within the file you are reading in. This isn't a hash of hashes as it stands - %MacroA
consists of only one level of hashes at the moment.
The first issue is that you are trying to define your hash using a list of the keys you want to use.
my %MacroA = ('Category', 'Item', 'Description', 'Score');
What you are actually doing here is trying to pass an array
of your keys. If you give a hash an array, it will interpret the first element as its key, the second as that key's value, the third as the second key, and so on. So you will end up with this
%MacroA = (
Category => Item,
Description => Score
)
To initialise the hash for just one level of keys, you could give each key an initial count of 0:
my %MacroA = ('Category', 0, 'Item', 0, 'Description', 0, 'Score', 0);
This is usually written with arrow symbols =>
to make things more clear
my %MacroA = ('Category' => 0, 'Item' => 0, 'Description' => 0, 'Score', 0);
To intialise the hash for a second level of keys you could do this (as you correctly suggested in the comments)
my %MacroA = ('Category' => {}, 'Item' => {}, 'Description' => {}, 'Score', {});
In fact, you don't even need to initialise your hash to keys with empty values because perl will use autovivification to initialise an empty key when you first use it. So all you really have to do is initialise the hash variable like so
my %MacroA;
I will take a guess here and assume you meant to have Category, Description etc. as your first level of keys and then whatever you find in your file as the second level of keys. I think you want to count the number of times the second level of keys occur.
At the moment, your hash is keeping track of Category, Item... keys because you are incrementing the values stored with these keys:
$MacroA{Category}++;
Because your regex matches will return whatever they matched into the scalar variable $1
, you can use that to increment a second level of hashes like so:
$MacroA{Category}->{$1}++;
Lastly, when printing out your counts, you make the simple mistake of referencing your key strings with a variable:
$MacroA{$Category}
Where you probably meant to use a string for each of the first level keys:
$MacroA{'Category'};
Perl thinks you are trying to use an undefined variable called $Category
and so throws the errors you are getting.
Finally, it will definitely help your understanding if you print Dumper
formatted logs of your data structures at certain points in your code. Just use the code
use Data::Dumper;
print Dumper(\%MacroA);
at any point in your script to view the structure of %MacroA
at that point in time.
Hopefully this helps you to struggle on!