Making a dynamic hash of arrays in foreach in perl based on regex -
so i'm trying make hash of arrays based on regex inside foreach.
i'm getting file paths, , of format:
longfilepath/name.action.gz
so there files same name diffent actions, want make hash keys of name arrays of actions. i'm apparently doing wrong keep getting error when run code:
not array reference @ ....the file i'm writing in
which don't since i'm checking see if set, , if not declaring array. i'm still getting used perl, i'm guessing problem simple.
i should say, i've verified regex generating both 'name' , 'action' strings problem in foreach;
thanks help. :)
my code thus.
my %my_hash; $file_paths = glom("/this/is/mypath/*.*\.gz"); foreach $path (@$bdr_paths){ $path =~ m"\/([^\/\.]+)\.([^\.]+)\.gz"; print stderr "=>".dumper($1)."\n\r"; print stderr "=>".dumper($2)."\n\r"; #add entity type hash recipe key if($my_hash{$1}) { push($my_hash{$1}, $2); } else { $my_hash{$1} = ($2); } }
it’s glob
, not glom
. in glob expressions, period no metacharacter. → glob '/this/is/mypath/*.gz'
.
the whole reason of using alternate regex delimiters avoid unneccessary escapes. forward slash no regex metacharacter, delimiter. inside charclasses, many operators loose specialness; no need escape period. ergo m!/([^/.]+)\.([^.]+)\.gz!
.
don't append \n\r
output. ① dumper
function appends newline. ② if on os expects crlf, use :crlf
perlio layer, transforms \n
s crlf. can add layers via binmode stdout, ':crlf'
. ③ if doing networking, might better specify exact bytes want emit, e.g. \x0a\x0d
or \012\015
. (but in case, remove perlio layers).
using references first arg push
doesn't work on perls older v5.14.
don't manually check whether populated slot in hash or not; if undef
, used arrayref, array reference automatically created there. known autovivification. of course, requires perform dereference (and skip short form push
).
in perl, parens only sort out precedence, , create list context when used on lhs of assignment. not create arrays. create anonymous array reference, use brackets: [$var]
. using parens useless; $x = $y
, $y = ($y)
absolutely identical.
so either want
push @{ $my_hash{$1} }, $2;
or
if ($my_hash{$1}) { push $my_hash{$1}, $2; } else { $my_hash{$1} = [$2]; }
edit: 3 things overlooked.
if glob
used in scalar context, turns iterator. unwanted, unless when used in while(my $path = glob(...)) { ... }
fashion. otherwise more difficult make sure iterator exhausted. rather, use glob
in list context matches @ once: my @paths = glob(...)
.
where $bdr_paths
come from? inside?
always check regex matched. can avoid subtle bugs, captures $1
etc. keep value until next successful match.
Comments
Post a Comment