Wednesday, April 20, 2011

Matched elements using regex in Perl

I have a hash which contains a regular expression: the number of matches to be captured in it and variables and their position of match. For example:

my %hash = (
    reg_ex => 'Variable1:\s+(.*?)\s+\n\s+Variable2:\s+(.*?)\s+\n',
    count => 2,
    Variable1 => 1,
    Variable2  => 2,
);

I am going to use this regex in some other part of code where I will be just giving say $to_be_matched_variable =~ /$hash{reg_ex}/ and we obtain the required matches here in $1, $2, ...

I need to use the value of the key Variable1, which indicates the number of the match to be used in place where we normally use $1.

I tried giving $.$hash{Variable1} and $,$hash{Variable1}. I am not able to find how to frame something that will be equivalent to $1, $2...

From stackoverflow
  • Try:

    (my @ArrayOfMatches) = $to_be_matched_variable =~ /$hash{reg_ex}/;
    
    my $Variable1 = $ArrayOfMatches[$hash{Variable1}];
    
    jpalecek : AFAIK, this doesn't work - the global match returns all matches of all parentheses in the string. Without /g, it would return ($1, $2, ...) as the OP needed.
    Meenakshi : It worked without the /g. Thanks.
    dreamlax : Yeah, whoops! I knew that too. I always type g out of habit and figure out later that it's not what I want!
  • ($1, $2, $3, ...., $9)[$hash{Variable1}]

    dreamlax : Wow! How very implicit! How very Perl ;)
    Ingo : yes, unlike MyFineArrayOfMatchesWhereIStoreMyMatchesYouKnow. :)
  • Since you are already using a hash, you might as well use the builtin %+ which maps names to matches. Thus if you changed your regexes to named matching, you could easily use %+ to retrieve the matched parts.

    $reg_ex = 'Variable1:\s+(?<foo>.*?)\s+\n\s+Variable2:\s+(?<bar>.*?)\s+\n';
    

    After a successful match, %+ should have the keys foo and bar and the values will correspond to what was matched.

    Thus your original hash could be changed to something like this:

    my %hash = (
        reg_ex => 'Variable1:\s+(?<foo>.*?)\s+\n\s+Variable2:\s+(?<bar>.*?)\s+\n',
        groups => [ 'foo', 'bar' ],
    );
    
    brian d foy : Named captures are the way to go if you can use Perl 5.10. There's a capture in _Learning Perl_ about them. :)

0 comments:

Post a Comment