in reply to Multiple matches of a regex

Look for @+ and @- in perldoc perlvar.

Replies are listed 'Best First'.
Re: Re: Multiple matches of a regex
by pike (Monk) on Jan 10, 2003 at 16:36 UTC
    Thanks for the tip, Fletch! (Can't ++ you today, ran out of votes... Wait for monday please!) So that leaves me with:

    use strict; my $regex = qr/(\d\d):(\d\d)(?::(\d\d))?/; # 01234567890123456 my $string = "11:30 or 11:29:53"; my $res; while ($string =~ /$regex/g) { my $pos = $-[0]; my ($ind, @match); for $ind (1..$#-) { push @match, substr ($string, $-[$ind], $+[$ind] - $-[$ind]); } $res->{$pos} = \@match; } use Data::Dumper; print Data::Dumper::Dumper $res;
    This prints:
    $VAR1 = { '0' => [ '11', '30' ], '9' => [ '11', '29', '53' ] };
    as it should.

    What I don't like about this solution is that it involves a lot of substr calls to get strings that are stored in the $n variables anyway. Is there a better way to do this?

    Thanks,

    pike

      As you are using capturing brackets within your regex, your required substrings are already being placed into the variables $1 $2 $3, so there is no need to use substr to isolate the substrings a second time. The only tricky bit is that $3 may have no value, so I've used grep to exclude it if it has no value.

      #! perl -slw use strict; use Data::Dumper; my $regex = qr/(\d\d):(\d\d)(?::(\d\d))?/; # 01234567890123456 my $string = "11:30 or 11:29:53"; my $res; $res->{$-[0]} = [grep $_, $1, $2, $3] while $string =~ /$regex/g; print Dumper $res; __END__ c:\test>225814 $VAR1 = { '0' => [ '11', '30' ], '9' => [ '11', '29', '53' ] }; c:\test>

      Examine what is said, not who speaks.

      The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      If you have anything against substr calls you can do this symbolically (through more people will probably have something against this than repeated substr calls).
      no strict 'refs'; my @groups = map $$_, 1 .. $#+;
      If I shall be picky, in your question you wanted the first match to return   ['11', '30', undef] while in your reply you said   ['11', '30'] is what you want. As I pointed out here you should consider the difference between $#+ and $#-. Also, unmatched groups would be '' with your code. Perhaps that's what you want, but it won't be fully analogous to using the $<DIGITS> variables. If done symbolically it sure will be analogous though, since you actually use the $<DIGITS> variables.

      Hope I've helped,
      ihb