jeanluca has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks

I tried to extract a list of modules installed on my system by the following code
sub _find_modules { my $dir = shift ; my ($inst) = ExtUtils::Installed->new(); my $packlist = $inst->packlist("My_Package"); return grep { s/(.*?\Q$dir\E)(\w+)(\.pm)$/$2/ } %$packlist ; }
So $dir contains a path specifying a specific sub_package.
Anyway, there seems tobe a problem with the $2, because running this code gives me the following warnings
Use of uninitialized value in pattern match (m//) at /usr/lib/perl5/si +te_perl/5.8.7/My_Package.pm line 309. Use of uninitialized value in pattern match (m//) at /usr/lib/perl5/si +te_perl/5.8.7/My_Package.pm line 309.
I get the feeling that this happens when $2 is not defined
Any suggestions whats wrong with this code and how to solve it?

Thanks a lot
LuCa

Replies are listed 'Best First'.
Re: warnings and grep problem
by Fletch (Bishop) on Jun 20, 2006 at 15:23 UTC

    Something doesn't quite . . . match up. Calling grep on %$packlist rather than (say) keys %$packlist seems odd. Not to mention you seem to be trying to use grep in one step where you probably want a map of grep'd results. Modifying things inside of a grep is . . . unusual; grep is for selecting items from a list which satisfy some predicate, map is for constructing a new list by applying some transformation to the elements of an existing list.

    Those things aside, I'd use FIle::Basename to split the paths apart instead of a regex.

      You're probably right (I'm still not very good with grep and map)
      Anyway I tried the following
      my $hash = map { /\Q$dir\E(\w+?)\.pm$/ and defined $1, $1 } keys %$pac +klist ;
      Looks a lot better,but printing it like
      foreach ( keys %hash) print $_ ; }
      gives a new warning
      Odd number of elements in hash assignment at /usr/lib/p....
      Any suggestions ?

      LuCa

        You're attempting to use the number of keys which matched to initialize a hash. Trying to use a single scalar to initialize a hash isn't going to produce anything useful.

        my @desired_keys = grep { /\Q$dir\E.*?\.pm$/ } keys %$packlist; my %hash; @hash{ map { /\Q$dir\E(\w+?)\.pm$/; $1 } @desired_keys } = @desired_ke +ys;

        Update: Gah. Me no write well. Reworded to (hopefully) clarify.

        You assigned the output of the map to a scalar $has so you'll just get the number of elements map returned, not the actual elements. Then you did keys %hash which is a whole new variable. The following might do what you want, but if you are messing with path/file names then i would highly recommend use a CPAN module.

        my @dirs = map { s/\Q$dir\E(\w+?)\.pm$/$1/ } keys %$packlist; for (@dirs) { print $_, "\n"; }

        ___________
        Eric Hodges
Re: warnings and grep problem
by Moron (Curate) on Jun 20, 2006 at 16:14 UTC
    The pattern doesn't match for every key and value of the hash, causing $2 to be undefined for such cases. To resolve that alone:
    sub _find_modules { my $dir = shift ; my ($inst) = ExtUtils::Installed->new(); my $packlist = $inst->packlist("My_Package"); return grep { /.*?\Q$dir\E\w+\.pm$/ and s/(.*?\Q$dir\E)(\w+)(\.pm) +$/$2/; } %$packlist ; }

    -M

    Free your mind

Re: warnings and grep problem
by OfficeLinebacker (Chaplain) on Jun 20, 2006 at 14:54 UTC
    It's not matching the second regular expression grouping; are you sure the first group isn't being too "greedy?"

    UPDATE: Also, I may be reading this wrong, but shouldn't there be a g after the regular expression? (meaning you want to do this for all modules, not just the first one)

    _________________________________________________________________________________

    I like computer programming because it's like Legos for the mind.

      when use
      return grep { s/(\Q$dir\E)(\w+)(\.pm)$/$2/g } %$packlist ; or return grep { s/(\Q$dir\E)(\w+?)(\.pm)$/$2/g } %$packlist ;
      gives me the same errors.
      I think this problem occures when it encounters something like /usr/lib/perl5/site_perl/5.8.7/My_Package/Sub_Package/Some_Module.pm.swp

      Luca
Re: warnings and grep problem
by Jasper (Chaplain) on Jun 20, 2006 at 16:33 UTC
    It's almost certainly to do with running the regex on both the key and the value of the hash. Probably some of the values of a packlist object (returned by ExtUtils::Installed->new->packlist()) are undefined... Is there a function of that packlist that returns what you want, rather than dumping the whole object hash?

    There's no point in doing /match/ && s/match/foo/ that's silly. Instead, try something like  defined && s/match/foo/ inside the grep.

    But know what you want to run the substitution on first (and other people have suggested this, I know) and do it only on those...