Given a regex in perl, how do I find the maximum number of captured groups in that regex? I know that I can use $1, $2 etc to reference the first, second etc captured groups. But how do I find the maximum number of such groups? By captured groups, I mean the string matched by a regex in paranthesis. For ex: if the regex is (a+)(b+)c+ then the string "abc" matches that regex. And the first captured group will be $1, second will be $2.
3 Answers
amon
hinted at the answer to this question when he mentioned the %+
hash. But what you need is the @+
array:
@+
This array holds the offsets of the ends of the last successful submatches in the currently active dynamic scope. $+[0] is the offset into the string of the end of the entire match. This is the same value as what the pos function returns when called on the variable that was matched against. The nth element of this array holds the offset of the nth submatch, so $+1 is the offset past where $1 ends, $+[2] the offset past where $2 ends, and so on. You can use $#+ to determine how many subgroups were in the last successful match. See the examples given for the @- variable. [enphasis added]
$re = "(.)" x 500;
$str = "a" x 500;
$str =~ /$re/;
print "Num captures is $#+"; # outputs "Num captures is 500"

- 117,087
- 18
- 149
- 283
The number of captures is effectivly unlimited. While there can only be nine captures that you can access with the $1
–$9
variables, you can use more capture groups.
If you have more than a few capture groups, you might want to use named captures, like
my $str = "foobar";
if ($str =~ /(?<name>fo+)/) {
say $+{name};
}
Output: foo
. You can access the values of named captures via the %+
hash.

- 57,091
- 2
- 89
- 149
-
I realise that the number of captures is unlimited. But it cant be unlimited for a given regex right? By captured groups, I mean the part of the regex within paranthesis that matches a given string. – Arjun Jul 10 '13 at 22:57
-
1`$10`, `$11`, [etc.](http://stackoverflow.com/a/12117671/168657) also work if there are more than 9 groups. – mob Jul 10 '13 at 23:00
You can use code like the following to give you a count of capture groups:
$regex = qr/..../; # Some arbitrary regex with capture groups
my @capture = '' =~ /$regex|()/; # A successful match incorporating the regex
my $groups_in_my_regex = scalar(@capture) - 1;
The way it works is that it performs a match which must succeed and then checks how many capture groups were created. (An extra one is created due to the trailing |()
Edit: Actually, it doesn't seem to be necessary to append an extra capture group. Just so long as the match is guaranteed to succeed then the array will contain an entry for every capture group.
So we can change the 2nd and 3rd lines to:
my @capture = '' =~ /$regex|/; # A successful match incorporating the regex
my $groups_in_my_regex = scalar(@capture);
See also:
Count the capture groups in a qr regex?

- 1
- 1

- 13,486
- 7
- 36
- 60