Reputation: 59
I have a string from a for loop:
@file = "/path/window/*_testing_42.csv";
foreach $file(@file) {
$name = $file=~ /(\w*)_testing_42/; #comes from file path
$name = 1$;
print $name; #prints G43B76P90T45
}
There are 4 values I am I need from this string (G43, B76, P90, T45). I want to place these into a hash so that I can refer to each value specifically. However the hash table code I am trying to implement is not working for my intended purpose:
my %hash;
foreach $file(@file) {
$name = $file=~ /(\w*)_testing_42/; #comes from file path
$name = 1$;
print $name; #prints G43B76P90T45
my($first $second $third $fourth) = $name;
$hash{"first"} = $first;
$hash{"second"} = $second;
$hash{"third"} = $third;
$hash{"fourth"} = $fourth;
EXPECTED OUTPUT:
print $fourth; #should print T45
print $first; #should print G43
print $third #should print P90
}
Upvotes: 1
Views: 533
Reputation: 6998
If I understand correctly what you're trying to do, then @Gever's answer should do the trick. Here's an alternative implementation using regexes rather than unpack:
use 5.010;
use strict;
use warnings;
my @file = glob("/path/window/*_testing_42.csv");
foreach my $file (@file) {
my($name) = $file =~ /(\w+)_testing_42/;
my @code = $name =~ /(...)/g;
say 'Parts found: ', scalar(@code); # Parts found: 4
say $code[0]; # G43
say $code[1]; # B76
say $code[2]; # P90
say $code[3]; # T45
}
I used an array rather than a hash, because that makes more sense to me, but if you really want a hash, you could do it like this:
foreach my $file (@file) {
my($name) = $file =~ /(\w+)_testing_42/;
my %hash;
@hash{'first', 'second', 'third', 'fourth'} = $name =~ /(...)/g;
say $hash{first}; # G43
say $hash{second}; # B76
say $hash{third}; # P90
say $hash{fourth}; # T45
}
In this line:
my($name) = $file =~ /(\w+)_testing_42/;
The parentheses around $name
are important because they force the match to be evaluated in list context, which returns the parts of the regex that were captured in the (\w+)
. Without the parentheses, the value 1 would be assigned to $name
because there was 1 match.
The syntax for assigning a list of values to a series of keys in a hash (called a 'hash slice') is somewhat confusing. Perl knows we're assigning values into %hash
because of the {
after the variable name, but we put a @
before the variable name to indicate we're assigning multiple values to a hash slice. Using a $
before the variable name would indicate we're assigning to a single value in the hash.
The other thing I changed from your code is that I declared %hash
inside the loop. Which means that you can only refer to it inside the loop. If you declare it outside the loop, one set of values will persist after each matching filename has been processed, but the hash might contain values from different filenames depending on how many fields were present on the last iterations.
Upvotes: 1
Reputation: 23
First you need to split the name in 4 parts:
my ($first, $second, $third, $fourth) = unpack("(A3)*", $name);
Fill the hash
$hash{"first"} = $first;
$hash{"second"} = $second;
$hash{"third"} = $third;
$hash{"fourth"} = $fourth;
and print the hash
print $hash{"fourth"};
Upvotes: 1