bpj
bpj

Reputation: 169

Python equivalent of Perl $+ aka $LAST_PAREN_MATCH

(Apologies if this is a duplicate, but it is impossible to google/search $+!)

I'm looking for the nearest/best equivalent to Perl's $+ aka $LAST_PAREN_MATCH.

For those who don't know Perl it is described like this:

$LAST_PAREN_MATCH
$+      The text matched by the last bracket of the last successful search
        pattern. This is useful if you don't know which one of a set of
        alternative patterns matched.

That is if I have a pattern like (b)|(a)|(r) then $+ will contain either b, a or r depending on which subpattern matched.

The best that I have is

next((g for g in reversed(match.groups(None)) if g is not None),None)[0]

Which seems like a lot of code for a simple thing to a longtime Perl hacker. (Not that I'm unaware that I could wrap it in a function last_paren_match(match) :-)

Upvotes: 3

Views: 258

Answers (2)

ThisSuitIsBlackNot
ThisSuitIsBlackNot

Reputation: 24063

You can use the MatchObject's lastindex attribute:

The integer index of the last matched capturing group, or None if no group was matched at all. For example, the expressions (a)b, ((a)(b)), and ((ab)) will have lastindex == 1 if applied to the string 'ab', while the expression (a)(b) will have lastindex == 2, if applied to the same string.

For example:

>>> import re
>>> m = re.match(r'(b)|(a)|(r)', 'abc')
>>> m.group(m.lastindex)
'a'

Note that this is different from Perl's $+ when you have nested capturing groups:

$ python -c'import re; m = re.match(r"((a)(b))", "ab"); print m.group(m.lastindex)'
ab
$ perl -E'"ab" =~ /((a)(b))/; say $+'
b

Personally, I would just capture the entire alternation instead of capturing each alternative separately:

>>> m = re.match(r'(b|a|r)', 'abc')
>>> m.group(1)
'a'

Upvotes: 1

Borodin
Borodin

Reputation: 126722

There may be no equivalent in Python, but if you use the branch reset pattern (?|...) then each alternation pipe | in the pattern will reset the counter for the capture variables. I'm pretty sure that will be supported in Python

In this example, all capture groups are saved in $1

use strict;
use warnings 'all';
use feature 'say';

'zax' =~ /(?|(b)|(a)|(r))/;

say $1;

output

a

Upvotes: 7

Related Questions