Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

named captures that match more than once (Perl)

Tags:

regex

perl

When I run this code:

$_='xaxbxc';
if(/(x(?<foo>.))+/) {
    say "&: ", $&;
    say "0: ", $-{foo}[0];
    say "1: ", $-{foo}[1];
 }

I get:

&: xaxbxc
0: c
1:

I understand that this is how it's supposed to work, but I would like to be able to somehow get the list of all matches ('a', 'b', 'c') instead of just the last match (c). How can I do this?

like image 359
JoelFan Avatar asked Nov 23 '10 16:11

JoelFan


People also ask

What does !~ Mean in Perl?

!~ is the negation of the binding operator =~ , like != is the negation of the operator == . The expression $foo !~ /bar/ is equivalent, but more concise, and sometimes more expressive, than the expression !($foo =~ /bar/)

What is * in Perl regex?

Regular Expression (Regex or Regexp or RE) in Perl is a special text string for describing a search pattern within a given text. Regex in Perl is linked to the host language and is not the same as in PHP, Python, etc. Sometimes it is termed as “Perl 5 Compatible Regular Expressions“.

What is pattern matching in Perl?

m operator in Perl is used to match a pattern within the given text. The string passed to m operator can be enclosed within any character which will be used as a delimiter to regular expressions.

What does $1 do in Perl?

The $number variables contain the parts of the string that matched the capture groups ( ... ) in the pattern for your last regex match if the match was successful. $1 equals the text " brown ".


2 Answers

I don't think there is a way to do this in general (please correct me if I am wrong), but there is likely to be a way to accomplish the same end-goal in specific situations. For example, this would work for your specific code sample:

$_='xaxbxc';
while (/x(?<foo>.)/g) {
    say "foo: ", $+{foo};
}

What exactly are you trying to accomplish? Perhaps we could find a solution for your actual problem even if there is no way to do repeating captures.

like image 41
Cameron Avatar answered Oct 22 '22 02:10

Cameron


In situations like these, using embeded code blocks provides an easy way out:

my @match;
$_='xaxbxc';
if(/((?:x(.)(?{push @match, $^N}))+)/) {
    say "\$1: ", $1;
    say "@match"
}

which prints:

$1: xaxbxc
a b c
like image 97
Eric Strom Avatar answered Oct 22 '22 04:10

Eric Strom