Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

global regex returning a list of arrays?

by LanX (Bishop)
on Feb 20, 2010 at 14:30 UTC ( #824385=perlquestion: print w/replies, xml ) Need Help??
LanX has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I was wondering about the best way to get the structure of a list of matches.

i.e. /($re1)($re2)/g produces a list of paired matches but when processing with map or grep you need a counter to know which item you got

 grep {  } $str=~/($re1)($re2)/g

Thats not very scalable...

Does anybody know a nifty way to get a list of arrays returned, like in

do {my @a; push @a, [$1,$2] while $str=~/($re1)($re2)/g; @a }

???

some code examples:

DB<16> $a=join "",0..3 DB<17> x $a=~/(.)(.)/g 0 0 1 1 2 2 3 3 DB<18> x do {my @a; push @a, [$1,$2] while $a=~/(.)(.)/g; @a } 0 ARRAY(0x8ed1a18) 0 0 1 1 1 ARRAY(0x8ed1ce8) 0 2 1 3

Cheers Rolf

BTW: couldn't find an array holding the values of $1,$2,... in the perldocs !?!

Replies are listed 'Best First'.
Re: global regex returning a list of arrays?
by Corion (Pope) on Feb 20, 2010 at 14:40 UTC

    perlvar lists @- and @+, but you still need a while loop to capture them:

    #!/usr/local/bin/perl use strict; use Data::Dumper; my $str = 'abacadabra'; my @matches; push @matches, [ map { substr $str, $-[$_], $+[$_]-$-[$_] } 1..$#+ ] while $str =~ /([ac])([bd])/g; print Dumper \@matches;
      yeah I knew this trick with the index-array, thx,!

      But it's not really comfortable to need to substr... :(

      Cheers Rolf

        BTW: couldn't find an array holding the values of $1,$2,... in the perldocs !?!

        Probably not much help in this particular case (and you still need to loop to capture), but 5.10 offers the %+ and %- predefined hashes for named captures (see perlvar) in place of an array of all capture groups:

        >perl -wMstrict -le "my $s = '12ab34cd56ef78'; my @pairs; push @pairs, [ $+{A}, $+{B} ] while $s =~ m{ (?<A>[[:alpha:]]) (?<B>[[:alpha:]]) }xmsg; use Data::Dumper; print Dumper \@pairs; " $VAR1 = [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ];
Re: global regex returning a list of arrays?
by AnomalousMonk (Chancellor) on Feb 20, 2010 at 17:32 UTC

    Perhaps more scalable, but still involving an explicit loop:

    >perl -wMstrict -le "use List::MoreUtils qw(natatime); use Data::Dumper; my $s = 'ab123cd456ef789gh'; my $triad = natatime 3, $s =~ m{ (\d) (\d) (\d) }xmsg; while (my @three = $triad->()) { print Dumper \@three; } " $VAR1 = [ '1', '2', '3' ]; $VAR1 = [ '4', '5', '6' ]; $VAR1 = [ '7', '8', '9' ];
      Ok if we include MoreUtils we could use part which does what I wanted without an explicit while:

      DB<41> use List::MoreUtils "part" DB<42> $a=join " ",0..5 DB<43> x part {my $i++/2} $a =~/(\w) (\w)/g 0 ARRAY(0x90c6430) 0 0 1 1 1 ARRAY(0x90c68a0) 0 2 1 3 2 ARRAY(0x90c68b0) 0 4 1 5

      but after considering MoreUtils it's only a small step to define a specialized functional solution fold (&) on one's own...

       grep { } fold { $a =~/(\w) (\w)/g } .

      Cheers Rolf

        ...it's only a small step to define a specialized functional solution fold (&) on one's own...

        hmm not as easy as I thought

        $a=join " ",0..7; sub fold (&) { my @a; push @a, [$1,$2] while $_[0]->(); @a}; print Dumper fold { $a =~/(\w) (\w)/g };

        seems like $1,$2 can't leave the scope of the coderef...

        Cheers Rolf

        UPDATE: c&p error in code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://824385]
Approved by Corion
Front-paged by almut
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (6)
As of 2017-12-16 19:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What programming language do you hate the most?




















    Results (458 votes). Check out past polls.

    Notices?